blob: df578583c3863d264f02fea498d4e371f04c1857 [file] [log] [blame]
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -07001import pdb
Sapan Bhatiac4f803f2017-04-21 11:50:39 +02002import re
Sapan Bhatia7886e122017-05-17 11:19:39 +02003from pattern import en
4
Sapan Bhatiaf7934b52017-06-12 05:04:23 -07005class FieldNotFound(Exception):
6 def __init__(self, message):
7 super(FieldNotFound, self).__init__(message)
8
Sapan Bhatia943dad52017-05-19 18:41:01 +02009def xproto_unquote(s):
10 return unquote(s)
11
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020012def unquote(s):
13 if (s.startswith('"') and s.endswith('"')):
14 return s[1:-1]
15
16def xproto_singularize(field):
17 try:
18 # The user has set a singular, as an exception that cannot be handled automatically
19 singular = field['options']['singular']
20 singular = unquote(singular)
21 except KeyError:
22 singular = en.singularize(field['name'])
23
24 return singular
25
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +020026def xproto_singularize_pluralize(field):
27 try:
28 # The user has set a plural, as an exception that cannot be handled automatically
29 plural = field['options']['plural']
30 plural = unquote(plural)
31 except KeyError:
32 plural = en.pluralize(en.singularize(field['name']))
33
34 return plural
35
Sapan Bhatia7886e122017-05-17 11:19:39 +020036def xproto_pluralize(field):
37 try:
38 # The user has set a plural, as an exception that cannot be handled automatically
39 plural = field['options']['plural']
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020040 plural = unquote(plural)
Sapan Bhatia7886e122017-05-17 11:19:39 +020041 except KeyError:
42 plural = en.pluralize(field['name'])
43
44 return plural
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020045
Sapan Bhatiad022aeb2017-06-07 15:49:55 +020046def xproto_links_to_modeldef_relations(llst):
47 outlist = []
48 seen = []
49 for l in llst:
50 try:
51 t = l['link_type']
52 except KeyError, e:
53 raise e
54
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020055 if l['peer']['fqn'] not in seen and t!='manytomany':
56 outlist.append('- {model: %s, type: %s}\n'%(l['peer']['name'], l['link_type']))
Sapan Bhatiad022aeb2017-06-07 15:49:55 +020057 seen.append(l['peer'])
58
59 return outlist
60
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070061
Sapan Bhatia4e80a262017-05-19 23:10:51 +020062def xproto_base_def(model_name, base):
63 if (model_name=='XOSBase'):
64 return '(models.Model, PlModelMixIn)'
65 elif (not base):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070066 return ''
67 else:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020068 base = map(lambda s:s['name'], base)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070069 return '(' + ','.join(base) + ')'
70
Sapan Bhatia504cc972017-04-27 01:56:28 +020071def xproto_first_non_empty(lst):
72 for l in lst:
73 if l: return l
74
Sapan Bhatia943dad52017-05-19 18:41:01 +020075def xproto_api_type(field):
76 try:
77 if (unquote(field['options']['content_type'])=='date'):
78 return 'float'
79 except KeyError:
80 pass
81
82 return field['type']
83
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020084
85def xproto_base_name(n):
86 # Hack - Refactor NetworkParameter* to make this go away
87 if (n.startswith('NetworkParameter')):
88 return '_'
89
Sapan Bhatia4e80a262017-05-19 23:10:51 +020090 expr = r'^[A-Z]+[a-z]*'
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020091
92 try:
93 match = re.findall(expr, n)[0]
94 except:
95 return '_'
96
97 return match
Sapan Bhatiaae9645c2017-05-05 15:35:54 +020098
Sapan Bhatia943dad52017-05-19 18:41:01 +020099def xproto_base_fields(m, table):
100 fields = []
101
102 for b in m['bases']:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200103 option1 = b['fqn']
104 try:
105 option2 = m['package'] + '.' + b['name']
106 except TypeError:
107 option2 = option1
Sapan Bhatia943dad52017-05-19 18:41:01 +0200108
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200109 accessor = None
110 if option1 in table: accessor = option1
111 elif option2 in table: accessor = option2
112
113 if accessor:
114 base_fields = xproto_base_fields(table[accessor], table)
115
116 model_fields = table[accessor]['fields']
Sapan Bhatia943dad52017-05-19 18:41:01 +0200117 fields.extend(base_fields)
118 fields.extend(model_fields)
119
120 return fields
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200121
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200122def xproto_base_rlinks(m, table):
123 links = []
124
125 for base in m['bases']:
126 b = base['name']
127 if b in table:
128 base_rlinks = xproto_base_rlinks(table[b], table)
129
130 model_rlinks = table[b]['rlinks']
131 links.extend(base_rlinks)
132 links.extend(model_rlinks)
133
134 return links
135
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200136def xproto_base_links(m, table):
137 links = []
138
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200139 for base in m['bases']:
140 b = base['name']
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200141 if b in table:
142 base_links = xproto_base_links(table[b], table)
143
144 model_links = table[b]['links']
145 links.extend(base_links)
146 links.extend(model_links)
147 return links
148
149
150def xproto_validators(f):
151 # To be cleaned up when we formalize validation in xproto
152 validators = []
153
154 # bound-based validators
155 bound_validators = [('max_length','maxlength'), ('min', 'min'), ('max', 'max')]
156
157 for v0, v1 in bound_validators:
158 try:
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200159 validators.append({'name':v1, 'int_value':int(f['options'][v0])})
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200160 except KeyError:
161 pass
162
163 # validators based on content_type
164 content_type_validators = ['ip', 'url', 'email']
165
166 for v in content_type_validators:
167 #if f['name']=='ip': pdb.set_trace()
168 try:
169 val = unquote(f['options']['content_type'])==v
170 if not val:
171 raise KeyError
172
173 validators.append({'name':v, 'bool_value': True})
174 except KeyError:
175 pass
176
177 # required validator
178 try:
179 required = f['options']['blank']=='False' and f['options']['null']=='False'
180 if required:
181 validators.append({'name':'required', 'bool_value':required})
182 except KeyError:
183 pass
184
185 return validators
186
187def xproto_string_type(xptags):
188 try:
189 max_length = eval(xptags['max_length'])
190 except:
191 max_length = 1024
192
193 if ('varchar' not in xptags):
194 return 'string'
195 else:
196 return 'text'
197
198def xproto_type_to_ui_type(f):
199 try:
200 content_type = f['options']['content_type']
201 content_type = eval(content_type)
202 except:
203 content_type = None
204 pass
205
206 if content_type == 'date':
207 return 'date'
208 elif f['type'] == 'bool':
209 return 'boolean'
210 elif f['type'] == 'string':
211 return xproto_string_type(f['options'])
212 elif f['type'] in ['int','uint32','int32'] or 'link' in f:
213 return 'number'
214 elif f['type'] in ['double','float']:
215 return 'string'
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700216
217def xproto_tuplify(nested_list_or_set):
218 if not isinstance(nested_list_or_set, list) and not isinstance(nested_list_or_set, set):
219 return nested_list_or_set
220 else:
221 return tuple([xproto_tuplify(i) for i in nested_list_or_set])
222
223def xproto_field_graph_components(fields, tag='unique_with'):
224 def find_components(graph):
225 pending = set(graph.keys())
226 components = []
227
228 while pending:
229 front = { pending.pop() }
230 component = set()
231
232 while front:
233 node = front.pop()
234 neighbours = graph[node]
235 neighbours-=component # These we have already visited
236 front |= neighbours
237
238 pending-=neighbours
239 component |= neighbours
240
241 components.append(component)
242
243 return components
244
245 field_graph = {}
246 field_names = {f['name'] for f in fields}
247
248 for f in fields:
249 try:
250 tagged_str = unquote(f['options'][tag])
251 tagged_fields = tagged_str.split(',')
252
253 for uf in tagged_fields:
254 if uf not in field_names:
255 raise FieldNotFound('Field %s not found'%uf)
256
257 field_graph.setdefault(f['name'],set()).add(uf)
258 field_graph.setdefault(uf,set()).add(f['name'])
259 except KeyError:
260 pass
261
262 components = find_components(field_graph)
263 return components
264
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200265def xproto_api_opts(field):
266 options = []
267 if 'max_length' in field['options'] and field['type']=='string':
268 options.append('(val).maxLength = %s'%field['options']['max_length'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700269
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200270 try:
271 if field['options']['null'] == 'False':
272 options.append('(val).nonNull = true')
273 except KeyError:
274 pass
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700275
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200276 if 'link' in field and 'model' in field['options']:
277 options.append('(foreignKey).modelName = "%s"'%field['options']['model'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700278
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200279 if options:
280 options_str = '[' + ', '.join(options) + ']'
281 else:
282 options_str = ''
283
284 return options_str
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700285
Matteo Scandolo3b7857b2017-06-30 16:22:33 -0700286def xproto_tosca_required(null, blank, default=None):
287
288 if null == 'True' or blank == 'True' or default != 'False':
289 return "false"
290 return "true"
291
292def xproto_tosca_field_type(type):
293 """
294 TOSCA requires fields of type 'bool' to be 'boolean'
295 """
296 if type == "bool":
297 return "boolean"
298 else:
299 return type