blob: 029f6eb27e58a03be5413d2920475ad432cdc274 [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 Bhatiad4567592017-07-24 17:26:26 -04009def xproto_debug(**kwargs):
10 print kwargs
11 pdb.set_trace()
12
Sapan Bhatia943dad52017-05-19 18:41:01 +020013def xproto_unquote(s):
14 return unquote(s)
15
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020016def unquote(s):
17 if (s.startswith('"') and s.endswith('"')):
18 return s[1:-1]
19
20def xproto_singularize(field):
21 try:
22 # The user has set a singular, as an exception that cannot be handled automatically
23 singular = field['options']['singular']
24 singular = unquote(singular)
25 except KeyError:
26 singular = en.singularize(field['name'])
27
28 return singular
29
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +020030def xproto_singularize_pluralize(field):
31 try:
32 # The user has set a plural, as an exception that cannot be handled automatically
33 plural = field['options']['plural']
34 plural = unquote(plural)
35 except KeyError:
36 plural = en.pluralize(en.singularize(field['name']))
37
38 return plural
39
Sapan Bhatia7886e122017-05-17 11:19:39 +020040def xproto_pluralize(field):
41 try:
42 # The user has set a plural, as an exception that cannot be handled automatically
43 plural = field['options']['plural']
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020044 plural = unquote(plural)
Sapan Bhatia7886e122017-05-17 11:19:39 +020045 except KeyError:
46 plural = en.pluralize(field['name'])
47
48 return plural
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020049
Sapan Bhatiad022aeb2017-06-07 15:49:55 +020050def xproto_links_to_modeldef_relations(llst):
51 outlist = []
52 seen = []
53 for l in llst:
54 try:
55 t = l['link_type']
56 except KeyError, e:
57 raise e
58
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020059 if l['peer']['fqn'] not in seen and t!='manytomany':
60 outlist.append('- {model: %s, type: %s}\n'%(l['peer']['name'], l['link_type']))
Sapan Bhatiad022aeb2017-06-07 15:49:55 +020061 seen.append(l['peer'])
62
63 return outlist
64
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070065
Sapan Bhatia4e80a262017-05-19 23:10:51 +020066def xproto_base_def(model_name, base):
67 if (model_name=='XOSBase'):
68 return '(models.Model, PlModelMixIn)'
69 elif (not base):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070070 return ''
71 else:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +020072 base = map(lambda s:s['name'], base)
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070073 return '(' + ','.join(base) + ')'
74
Sapan Bhatia504cc972017-04-27 01:56:28 +020075def xproto_first_non_empty(lst):
76 for l in lst:
77 if l: return l
78
Sapan Bhatia943dad52017-05-19 18:41:01 +020079def xproto_api_type(field):
80 try:
81 if (unquote(field['options']['content_type'])=='date'):
82 return 'float'
83 except KeyError:
84 pass
85
86 return field['type']
87
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020088
89def xproto_base_name(n):
90 # Hack - Refactor NetworkParameter* to make this go away
91 if (n.startswith('NetworkParameter')):
92 return '_'
93
Sapan Bhatia4e80a262017-05-19 23:10:51 +020094 expr = r'^[A-Z]+[a-z]*'
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020095
96 try:
97 match = re.findall(expr, n)[0]
98 except:
99 return '_'
100
101 return match
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200102
Sapan Bhatia943dad52017-05-19 18:41:01 +0200103def xproto_base_fields(m, table):
104 fields = []
105
106 for b in m['bases']:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200107 option1 = b['fqn']
108 try:
109 option2 = m['package'] + '.' + b['name']
110 except TypeError:
111 option2 = option1
Sapan Bhatia943dad52017-05-19 18:41:01 +0200112
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200113 accessor = None
114 if option1 in table: accessor = option1
115 elif option2 in table: accessor = option2
116
117 if accessor:
118 base_fields = xproto_base_fields(table[accessor], table)
119
120 model_fields = table[accessor]['fields']
Sapan Bhatia943dad52017-05-19 18:41:01 +0200121 fields.extend(base_fields)
122 fields.extend(model_fields)
123
124 return fields
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200125
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200126def xproto_base_rlinks(m, table):
127 links = []
128
129 for base in m['bases']:
130 b = base['name']
131 if b in table:
132 base_rlinks = xproto_base_rlinks(table[b], table)
133
134 model_rlinks = table[b]['rlinks']
135 links.extend(base_rlinks)
136 links.extend(model_rlinks)
137
138 return links
139
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200140def xproto_base_links(m, table):
141 links = []
142
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200143 for base in m['bases']:
144 b = base['name']
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200145 if b in table:
146 base_links = xproto_base_links(table[b], table)
147
148 model_links = table[b]['links']
149 links.extend(base_links)
150 links.extend(model_links)
151 return links
152
153
154def xproto_validators(f):
155 # To be cleaned up when we formalize validation in xproto
156 validators = []
157
158 # bound-based validators
159 bound_validators = [('max_length','maxlength'), ('min', 'min'), ('max', 'max')]
160
161 for v0, v1 in bound_validators:
162 try:
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200163 validators.append({'name':v1, 'int_value':int(f['options'][v0])})
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200164 except KeyError:
165 pass
166
167 # validators based on content_type
168 content_type_validators = ['ip', 'url', 'email']
169
170 for v in content_type_validators:
171 #if f['name']=='ip': pdb.set_trace()
172 try:
173 val = unquote(f['options']['content_type'])==v
174 if not val:
175 raise KeyError
176
177 validators.append({'name':v, 'bool_value': True})
178 except KeyError:
179 pass
180
181 # required validator
182 try:
183 required = f['options']['blank']=='False' and f['options']['null']=='False'
184 if required:
185 validators.append({'name':'required', 'bool_value':required})
186 except KeyError:
187 pass
188
189 return validators
190
191def xproto_string_type(xptags):
192 try:
193 max_length = eval(xptags['max_length'])
194 except:
195 max_length = 1024
196
197 if ('varchar' not in xptags):
198 return 'string'
199 else:
200 return 'text'
201
202def xproto_type_to_ui_type(f):
203 try:
204 content_type = f['options']['content_type']
205 content_type = eval(content_type)
206 except:
207 content_type = None
208 pass
209
210 if content_type == 'date':
211 return 'date'
212 elif f['type'] == 'bool':
213 return 'boolean'
214 elif f['type'] == 'string':
215 return xproto_string_type(f['options'])
216 elif f['type'] in ['int','uint32','int32'] or 'link' in f:
217 return 'number'
218 elif f['type'] in ['double','float']:
219 return 'string'
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700220
221def xproto_tuplify(nested_list_or_set):
222 if not isinstance(nested_list_or_set, list) and not isinstance(nested_list_or_set, set):
223 return nested_list_or_set
224 else:
225 return tuple([xproto_tuplify(i) for i in nested_list_or_set])
226
227def xproto_field_graph_components(fields, tag='unique_with'):
228 def find_components(graph):
229 pending = set(graph.keys())
230 components = []
231
232 while pending:
233 front = { pending.pop() }
234 component = set()
235
236 while front:
237 node = front.pop()
238 neighbours = graph[node]
239 neighbours-=component # These we have already visited
240 front |= neighbours
241
242 pending-=neighbours
243 component |= neighbours
244
245 components.append(component)
246
247 return components
248
249 field_graph = {}
250 field_names = {f['name'] for f in fields}
251
252 for f in fields:
253 try:
254 tagged_str = unquote(f['options'][tag])
255 tagged_fields = tagged_str.split(',')
256
257 for uf in tagged_fields:
258 if uf not in field_names:
259 raise FieldNotFound('Field %s not found'%uf)
260
261 field_graph.setdefault(f['name'],set()).add(uf)
262 field_graph.setdefault(uf,set()).add(f['name'])
263 except KeyError:
264 pass
265
266 components = find_components(field_graph)
267 return components
268
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200269def xproto_api_opts(field):
270 options = []
271 if 'max_length' in field['options'] and field['type']=='string':
272 options.append('(val).maxLength = %s'%field['options']['max_length'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700273
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200274 try:
275 if field['options']['null'] == 'False':
276 options.append('(val).nonNull = true')
277 except KeyError:
278 pass
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700279
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200280 if 'link' in field and 'model' in field['options']:
281 options.append('(foreignKey).modelName = "%s"'%field['options']['model'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700282
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200283 if options:
284 options_str = '[' + ', '.join(options) + ']'
285 else:
286 options_str = ''
287
288 return options_str
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700289
Matteo Scandolo3b7857b2017-06-30 16:22:33 -0700290def xproto_tosca_required(null, blank, default=None):
291
292 if null == 'True' or blank == 'True' or default != 'False':
293 return "false"
294 return "true"
295
296def xproto_tosca_field_type(type):
297 """
298 TOSCA requires fields of type 'bool' to be 'boolean'
299 """
300 if type == "bool":
301 return "boolean"
302 else:
303 return type