blob: c15bf3283900ae2412b6651548d7b19da3dc200f [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 Bhatiaa3d2e622017-07-31 22:25:55 -040066def xproto_base_def(model_name, base, suffix='', suffix_list=[]):
Sapan Bhatia4e80a262017-05-19 23:10:51 +020067 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 Bhatiaa3d2e622017-07-31 22:25:55 -040072 int_base = [i['name']+suffix for i in base if i['name'] in suffix_list]
73 ext_base = [i['name'] for i in base if i['name'] not in suffix_list]
74 return '(' + ','.join(int_base + ext_base) + ')'
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070075
Sapan Bhatia504cc972017-04-27 01:56:28 +020076def xproto_first_non_empty(lst):
77 for l in lst:
78 if l: return l
79
Sapan Bhatia943dad52017-05-19 18:41:01 +020080def xproto_api_type(field):
81 try:
82 if (unquote(field['options']['content_type'])=='date'):
83 return 'float'
84 except KeyError:
85 pass
86
87 return field['type']
88
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020089
90def xproto_base_name(n):
91 # Hack - Refactor NetworkParameter* to make this go away
92 if (n.startswith('NetworkParameter')):
93 return '_'
94
Sapan Bhatia4e80a262017-05-19 23:10:51 +020095 expr = r'^[A-Z]+[a-z]*'
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020096
97 try:
98 match = re.findall(expr, n)[0]
99 except:
100 return '_'
101
102 return match
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200103
Sapan Bhatia943dad52017-05-19 18:41:01 +0200104def xproto_base_fields(m, table):
105 fields = []
106
107 for b in m['bases']:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200108 option1 = b['fqn']
109 try:
110 option2 = m['package'] + '.' + b['name']
111 except TypeError:
112 option2 = option1
Sapan Bhatia943dad52017-05-19 18:41:01 +0200113
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200114 accessor = None
115 if option1 in table: accessor = option1
116 elif option2 in table: accessor = option2
117
118 if accessor:
119 base_fields = xproto_base_fields(table[accessor], table)
120
121 model_fields = table[accessor]['fields']
Sapan Bhatia943dad52017-05-19 18:41:01 +0200122 fields.extend(base_fields)
123 fields.extend(model_fields)
124
125 return fields
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200126
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200127def xproto_base_rlinks(m, table):
128 links = []
129
130 for base in m['bases']:
131 b = base['name']
132 if b in table:
133 base_rlinks = xproto_base_rlinks(table[b], table)
134
135 model_rlinks = table[b]['rlinks']
136 links.extend(base_rlinks)
137 links.extend(model_rlinks)
138
139 return links
140
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200141def xproto_base_links(m, table):
142 links = []
143
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200144 for base in m['bases']:
145 b = base['name']
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200146 if b in table:
147 base_links = xproto_base_links(table[b], table)
148
149 model_links = table[b]['links']
150 links.extend(base_links)
151 links.extend(model_links)
152 return links
153
154
155def xproto_validators(f):
156 # To be cleaned up when we formalize validation in xproto
157 validators = []
158
159 # bound-based validators
160 bound_validators = [('max_length','maxlength'), ('min', 'min'), ('max', 'max')]
161
162 for v0, v1 in bound_validators:
163 try:
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200164 validators.append({'name':v1, 'int_value':int(f['options'][v0])})
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200165 except KeyError:
166 pass
167
168 # validators based on content_type
169 content_type_validators = ['ip', 'url', 'email']
170
171 for v in content_type_validators:
172 #if f['name']=='ip': pdb.set_trace()
173 try:
174 val = unquote(f['options']['content_type'])==v
175 if not val:
176 raise KeyError
177
178 validators.append({'name':v, 'bool_value': True})
179 except KeyError:
180 pass
181
182 # required validator
183 try:
184 required = f['options']['blank']=='False' and f['options']['null']=='False'
185 if required:
186 validators.append({'name':'required', 'bool_value':required})
187 except KeyError:
188 pass
189
190 return validators
191
192def xproto_string_type(xptags):
193 try:
194 max_length = eval(xptags['max_length'])
195 except:
196 max_length = 1024
197
198 if ('varchar' not in xptags):
199 return 'string'
200 else:
201 return 'text'
202
203def xproto_type_to_ui_type(f):
204 try:
205 content_type = f['options']['content_type']
206 content_type = eval(content_type)
207 except:
208 content_type = None
209 pass
210
211 if content_type == 'date':
212 return 'date'
213 elif f['type'] == 'bool':
214 return 'boolean'
215 elif f['type'] == 'string':
216 return xproto_string_type(f['options'])
217 elif f['type'] in ['int','uint32','int32'] or 'link' in f:
218 return 'number'
219 elif f['type'] in ['double','float']:
220 return 'string'
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700221
222def xproto_tuplify(nested_list_or_set):
223 if not isinstance(nested_list_or_set, list) and not isinstance(nested_list_or_set, set):
224 return nested_list_or_set
225 else:
226 return tuple([xproto_tuplify(i) for i in nested_list_or_set])
227
228def xproto_field_graph_components(fields, tag='unique_with'):
229 def find_components(graph):
230 pending = set(graph.keys())
231 components = []
232
233 while pending:
234 front = { pending.pop() }
235 component = set()
236
237 while front:
238 node = front.pop()
239 neighbours = graph[node]
240 neighbours-=component # These we have already visited
241 front |= neighbours
242
243 pending-=neighbours
244 component |= neighbours
245
246 components.append(component)
247
248 return components
249
250 field_graph = {}
251 field_names = {f['name'] for f in fields}
252
253 for f in fields:
254 try:
255 tagged_str = unquote(f['options'][tag])
256 tagged_fields = tagged_str.split(',')
257
258 for uf in tagged_fields:
259 if uf not in field_names:
260 raise FieldNotFound('Field %s not found'%uf)
261
262 field_graph.setdefault(f['name'],set()).add(uf)
263 field_graph.setdefault(uf,set()).add(f['name'])
264 except KeyError:
265 pass
266
267 components = find_components(field_graph)
268 return components
269
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200270def xproto_api_opts(field):
271 options = []
272 if 'max_length' in field['options'] and field['type']=='string':
273 options.append('(val).maxLength = %s'%field['options']['max_length'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700274
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200275 try:
276 if field['options']['null'] == 'False':
277 options.append('(val).nonNull = true')
278 except KeyError:
279 pass
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700280
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200281 if 'link' in field and 'model' in field['options']:
282 options.append('(foreignKey).modelName = "%s"'%field['options']['model'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700283
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200284 if options:
285 options_str = '[' + ', '.join(options) + ']'
286 else:
287 options_str = ''
288
289 return options_str
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700290
Matteo Scandolo3b7857b2017-06-30 16:22:33 -0700291def xproto_tosca_required(null, blank, default=None):
292
293 if null == 'True' or blank == 'True' or default != 'False':
294 return "false"
295 return "true"
296
297def xproto_tosca_field_type(type):
298 """
299 TOSCA requires fields of type 'bool' to be 'boolean'
300 """
301 if type == "bool":
302 return "boolean"
303 else:
304 return type