|
@@ -1,4 +1,9 @@
|
1
|
1
|
#-*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+## @package lodel.leapi.datahandlers.datas
|
|
4
|
+# This module contains specific datahandlers extending the basic ones from the lodel.leapi.datahandlers.datas_base module.
|
|
5
|
+
|
|
6
|
+
|
2
|
7
|
import warnings
|
3
|
8
|
import inspect
|
4
|
9
|
import re
|
|
@@ -12,22 +17,29 @@ LodelContext.expose_modules(globals(), {
|
12
|
17
|
'LodelFatalError', 'DataNoneValid', 'FieldValidationError']})
|
13
|
18
|
|
14
|
19
|
|
15
|
|
-##@brief Data field designed to handle formated strings
|
|
20
|
+## @brief Data field designed to handle formated strings
|
16
|
21
|
class FormatString(Varchar):
|
17
|
22
|
|
18
|
|
- help = 'Automatic string field, designed to use the str % operator to \
|
19
|
|
-build its content'
|
|
23
|
+ help = 'Automatic string field, designed to use the str % operator to build its content'
|
20
|
24
|
base_type = 'char'
|
21
|
25
|
|
22
|
|
- ##@brief Build its content with a field list and a format string
|
23
|
|
- # @param format_string str
|
24
|
|
- # @param field_list list : List of field to use
|
25
|
|
- # @param **kwargs
|
|
26
|
+ ## @brief Constructor
|
|
27
|
+ # @param _field_list list : List of fields to use
|
|
28
|
+ # @param _format_string str : formatted string
|
|
29
|
+ # @param **kwargs : additional options
|
26
|
30
|
def __init__(self, format_string, field_list, **kwargs):
|
27
|
31
|
self._field_list = field_list
|
28
|
32
|
self._format_string = format_string
|
29
|
33
|
super().__init__(internal='automatic', **kwargs)
|
30
|
34
|
|
|
35
|
+ ## @brief constructs the formatted string data
|
|
36
|
+ # The string can be truncated depending on the maximum length defined for this field.
|
|
37
|
+ #
|
|
38
|
+ # @param emcomponent EmComponent
|
|
39
|
+ # @param fname str
|
|
40
|
+ # @param datas dict
|
|
41
|
+ # @param cur_value str
|
|
42
|
+ # @return str
|
31
|
43
|
def _construct_data(self, emcomponent, fname, datas, cur_value):
|
32
|
44
|
ret = self._format_string % tuple(
|
33
|
45
|
datas[fname] for fname in self._field_list)
|
|
@@ -35,27 +47,28 @@ build its content'
|
35
|
47
|
warnings.warn("Format field overflow. Truncating value")
|
36
|
48
|
ret = ret[:self.max_length]
|
37
|
49
|
return ret
|
38
|
|
-
|
39
|
|
-##@brief Varchar validated by a regex
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+## @brief Varchar validated by a regex
|
40
|
53
|
class Regex(Varchar):
|
41
|
54
|
|
42
|
55
|
help = 'String field validated with a regex. Takes two options : \
|
43
|
56
|
max_length and regex'
|
44
|
57
|
base_type = 'char'
|
45
|
58
|
|
46
|
|
- ##@brief A string field validated by a regex
|
47
|
|
- # @param regex str : a regex string (passed as argument to re.compile())
|
|
59
|
+ ## @brief A string field validated by a regex
|
|
60
|
+ # @param regex str : a regex string (passed as argument to re.compile()), default value is an empty string
|
48
|
61
|
# @param max_length int : the max length for this field (default : 10)
|
49
|
|
- # @param **kwargs
|
|
62
|
+ # @param **kwargs : additional options
|
50
|
63
|
def __init__(self, regex='', max_length=10, **kwargs):
|
51
|
64
|
self.regex = regex
|
52
|
65
|
self.compiled_re = re.compile(regex) # trigger an error if invalid regex
|
53
|
66
|
super(self.__class__, self).__init__(max_length=max_length, **kwargs)
|
54
|
67
|
|
55
|
|
- ##@brief Check and cast value in appropriate type
|
56
|
|
- #@param value *
|
57
|
|
- #@throw FieldValidationError if value is unappropriate or can not be cast
|
58
|
|
- #@return value
|
|
68
|
+ ## @brief Check and cast value in appropriate type
|
|
69
|
+ # @param value *
|
|
70
|
+ # @throw FieldValidationError if value is unappropriate or can not be cast
|
|
71
|
+ # @return str
|
59
|
72
|
def _check_data_value(self, value):
|
60
|
73
|
value = super()._check_data_value(value)
|
61
|
74
|
if not self.compiled_re.match(value) or len(value) > self.max_length:
|
|
@@ -63,6 +76,10 @@ max_length and regex'
|
63
|
76
|
raise FieldValidationError(msg)
|
64
|
77
|
return value
|
65
|
78
|
|
|
79
|
+ ## @brief checks if another datahandler can override this one
|
|
80
|
+ #
|
|
81
|
+ # @param data_handler Datahandler
|
|
82
|
+ # @return bool
|
66
|
83
|
def can_override(self, data_handler):
|
67
|
84
|
if not super().can_override(data_handler):
|
68
|
85
|
return False
|
|
@@ -71,36 +88,58 @@ max_length and regex'
|
71
|
88
|
return False
|
72
|
89
|
return True
|
73
|
90
|
|
|
91
|
+
|
74
|
92
|
##@brief Handles uniq ID
|
75
|
93
|
class UniqID(Integer):
|
76
|
94
|
|
77
|
95
|
help = 'Fieldtype designed to handle editorial model UID'
|
78
|
96
|
base_type = 'int'
|
79
|
97
|
|
80
|
|
- ##@brief A uid field
|
81
|
|
- # @param **kwargs
|
|
98
|
+ ## @brief A uid field
|
|
99
|
+ #
|
|
100
|
+ # @param **kwargs dict
|
82
|
101
|
def __init__(self, **kwargs):
|
83
|
102
|
kwargs['internal'] = 'automatic'
|
84
|
103
|
super(self.__class__, self).__init__(primary_key = True, **kwargs)
|
85
|
104
|
|
|
105
|
+ ## @brief Constructs the field's data
|
|
106
|
+ # @param emcomponent EmComponent : Component corresponding to the field
|
|
107
|
+ # @param fname
|
|
108
|
+ # @param datas
|
|
109
|
+ # @param cur_value str : current value to use (is retrieved from the datasource if not given)
|
|
110
|
+ # @return str
|
|
111
|
+ # @remarks fname and datas are not used and should become non mandatory, cur_value should have a None default value
|
86
|
112
|
def construct_data(self, emcomponent, fname, datas, cur_value):
|
87
|
113
|
if cur_value is None:
|
88
|
114
|
#Ask datasource to provide a new uniqID
|
89
|
115
|
return emcomponent._ro_datasource.new_numeric_id(emcomponent)
|
90
|
116
|
return cur_value
|
91
|
117
|
|
|
118
|
+
|
|
119
|
+## @brief Class representing a LeObject subclass
|
92
|
120
|
class LeobjectSubclassIdentifier(Varchar):
|
93
|
121
|
|
94
|
122
|
help = 'Datahandler designed to handle LeObject subclass identifier in DB'
|
95
|
123
|
base_type = 'varchar'
|
96
|
124
|
|
|
125
|
+ ## @brief Constructor
|
|
126
|
+ # @param kwargs dict : additional options
|
|
127
|
+ # @throw RuntimeError
|
|
128
|
+ # @todo define the "internal" option that can be given in the kwargs, and document its meaning
|
97
|
129
|
def __init__(self, **kwargs):
|
98
|
130
|
if 'internal' in kwargs and not kwargs['internal']:
|
99
|
131
|
raise RuntimeError(self.__class__.__name__+" datahandler can only \
|
100
|
132
|
be internal")
|
101
|
133
|
kwargs['internal'] = True
|
102
|
134
|
super().__init__(**kwargs)
|
103
|
|
-
|
|
135
|
+
|
|
136
|
+ ## @brief Returns the class' name
|
|
137
|
+ # @param emcomponent EmComponent : Component correponding to the field
|
|
138
|
+ # @param fname
|
|
139
|
+ # @param datas
|
|
140
|
+ # @param cur_value
|
|
141
|
+ # @return str
|
|
142
|
+ # @remarks fname, datas and cur_value should be given default values as they are not mandatory here.
|
104
|
143
|
def construct_data(self, emcomponent, fname, datas, cur_value):
|
105
|
144
|
cls = emcomponent
|
106
|
145
|
if not inspect.isclass(emcomponent):
|
|
@@ -108,13 +147,13 @@ be internal")
|
108
|
147
|
return cls.__name__
|
109
|
148
|
|
110
|
149
|
|
111
|
|
-##@brief Data field designed to handle concatenated fields
|
|
150
|
+## @brief Data field designed to handle concatenated fields
|
112
|
151
|
class Concat(FormatString):
|
113
|
152
|
help = 'Automatic strings concatenation'
|
114
|
153
|
base_type = 'char'
|
115
|
154
|
|
116
|
|
- ##@brief Build its content with a field list and a separator
|
117
|
|
- # @param field_list list : List of field to use
|
|
155
|
+ ## @brief Build its content with a field list and a separator
|
|
156
|
+ # @param field_list list : List of fields to concatenate
|
118
|
157
|
# @param separator str
|
119
|
158
|
# @param **kwargs
|
120
|
159
|
def __init__(self, field_list, separator=' ', **kwargs):
|
|
@@ -124,22 +163,34 @@ class Concat(FormatString):
|
124
|
163
|
**kwargs)
|
125
|
164
|
|
126
|
165
|
|
|
166
|
+## @brief Datahandler managing a password
|
127
|
167
|
class Password(Varchar):
|
128
|
168
|
help = 'Handle passwords'
|
129
|
169
|
base_type = 'password'
|
130
|
170
|
pass
|
131
|
171
|
|
132
|
|
-
|
|
172
|
+## @brief Datahandler turning a string into a list
|
133
|
173
|
class VarcharList(Varchar):
|
134
|
174
|
help = 'DataHandler designed to make a list out of a string.'
|
135
|
175
|
base_type = 'varchar'
|
136
|
|
-
|
|
176
|
+
|
|
177
|
+ ## @brief Constructor
|
|
178
|
+ # @param delimiter str : default value is a whitespace character
|
|
179
|
+ # @param **kwargs : additional options
|
|
180
|
+ # @throw LodelException : this exception is raised when the delimiter is not a string
|
137
|
181
|
def __init__(self, delimiter=' ', **kwargs):
|
138
|
182
|
if not isinstance(delimiter, str):
|
139
|
183
|
raise LodelException("The delimiter has to be a string, %s given" % type(delimiter))
|
140
|
184
|
self.delimiter = str(delimiter)
|
141
|
185
|
super().__init__(**kwargs)
|
142
|
186
|
|
|
187
|
+ ## @brief Constructs the field's data
|
|
188
|
+ # @param emcomponent EmComponent
|
|
189
|
+ # @param fname
|
|
190
|
+ # @param datas
|
|
191
|
+ # @param cur_value : current value to use
|
|
192
|
+ # @return list
|
|
193
|
+ # @remarks emcomponent, fname and datas should be given a default value as they seem to be non mandatory
|
143
|
194
|
def construct_data(self, emcomponent, fname, datas, cur_value):
|
144
|
195
|
result = cur_value.split(self.delimiter)
|
145
|
196
|
return result
|