blob: 1293863b82d19289f3cfb3b0225c0325a29a7aad [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070017import pdb
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020018import re
Sapan Bhatia7886e122017-05-17 11:19:39 +020019from pattern import en
20
Sapan Bhatiaf7934b52017-06-12 05:04:23 -070021class FieldNotFound(Exception):
22 def __init__(self, message):
23 super(FieldNotFound, self).__init__(message)
24
Sapan Bhatiad4567592017-07-24 17:26:26 -040025def xproto_debug(**kwargs):
26 print kwargs
27 pdb.set_trace()
28
Sapan Bhatia943dad52017-05-19 18:41:01 +020029def xproto_unquote(s):
30 return unquote(s)
31
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020032def unquote(s):
33 if (s.startswith('"') and s.endswith('"')):
34 return s[1:-1]
Matteo Scandolo292cc2a2017-07-31 19:02:12 -070035 else:
36 return s
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020037
38def xproto_singularize(field):
39 try:
40 # The user has set a singular, as an exception that cannot be handled automatically
41 singular = field['options']['singular']
42 singular = unquote(singular)
43 except KeyError:
44 singular = en.singularize(field['name'])
45
46 return singular
47
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +020048def xproto_singularize_pluralize(field):
49 try:
50 # The user has set a plural, as an exception that cannot be handled automatically
51 plural = field['options']['plural']
52 plural = unquote(plural)
53 except KeyError:
54 plural = en.pluralize(en.singularize(field['name']))
55
56 return plural
57
Sapan Bhatia7886e122017-05-17 11:19:39 +020058def xproto_pluralize(field):
59 try:
60 # The user has set a plural, as an exception that cannot be handled automatically
61 plural = field['options']['plural']
Sapan Bhatia49b54ae2017-05-19 17:11:32 +020062 plural = unquote(plural)
Sapan Bhatia7886e122017-05-17 11:19:39 +020063 except KeyError:
64 plural = en.pluralize(field['name'])
65
66 return plural
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020067
Sapan Bhatiaa3d2e622017-07-31 22:25:55 -040068def xproto_base_def(model_name, base, suffix='', suffix_list=[]):
Sapan Bhatia4e80a262017-05-19 23:10:51 +020069 if (model_name=='XOSBase'):
70 return '(models.Model, PlModelMixIn)'
71 elif (not base):
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070072 return ''
73 else:
Sapan Bhatiaa3d2e622017-07-31 22:25:55 -040074 int_base = [i['name']+suffix for i in base if i['name'] in suffix_list]
75 ext_base = [i['name'] for i in base if i['name'] not in suffix_list]
76 return '(' + ','.join(int_base + ext_base) + ')'
Sapan Bhatiaff1b8fa2017-04-10 19:44:38 -070077
Sapan Bhatia504cc972017-04-27 01:56:28 +020078def xproto_first_non_empty(lst):
79 for l in lst:
80 if l: return l
81
Sapan Bhatia943dad52017-05-19 18:41:01 +020082def xproto_api_type(field):
83 try:
84 if (unquote(field['options']['content_type'])=='date'):
Scott Baker450e5d02017-09-06 11:18:16 -070085 return 'double'
Sapan Bhatia943dad52017-05-19 18:41:01 +020086 except KeyError:
87 pass
88
89 return field['type']
90
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020091
92def xproto_base_name(n):
93 # Hack - Refactor NetworkParameter* to make this go away
94 if (n.startswith('NetworkParameter')):
95 return '_'
96
Sapan Bhatia4e80a262017-05-19 23:10:51 +020097 expr = r'^[A-Z]+[a-z]*'
Sapan Bhatiac4f803f2017-04-21 11:50:39 +020098
99 try:
100 match = re.findall(expr, n)[0]
101 except:
102 return '_'
103
104 return match
Sapan Bhatiaae9645c2017-05-05 15:35:54 +0200105
Sapan Bhatia943dad52017-05-19 18:41:01 +0200106def xproto_base_fields(m, table):
107 fields = []
108
109 for b in m['bases']:
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200110 option1 = b['fqn']
111 try:
112 option2 = m['package'] + '.' + b['name']
113 except TypeError:
114 option2 = option1
Sapan Bhatia943dad52017-05-19 18:41:01 +0200115
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200116 accessor = None
117 if option1 in table: accessor = option1
118 elif option2 in table: accessor = option2
119
120 if accessor:
121 base_fields = xproto_base_fields(table[accessor], table)
122
123 model_fields = table[accessor]['fields']
Sapan Bhatia943dad52017-05-19 18:41:01 +0200124 fields.extend(base_fields)
125 fields.extend(model_fields)
126
Matteo Scandolo39b4a272017-11-17 11:09:21 -0800127 if 'no_sync' in m['options'] and m['options']['no_sync']:
128 fields = [f for f in fields if f['name'] != 'backend_status' and f['name'] != 'backend_code']
129
130 if 'no_policy' in m['options'] and m['options']['no_policy']:
131 fields = [f for f in fields if f['name'] != 'policy_status' and f['name'] != 'policy_code']
132
Sapan Bhatia943dad52017-05-19 18:41:01 +0200133 return fields
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200134
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200135def xproto_base_rlinks(m, table):
136 links = []
137
138 for base in m['bases']:
139 b = base['name']
140 if b in table:
141 base_rlinks = xproto_base_rlinks(table[b], table)
142
143 model_rlinks = table[b]['rlinks']
144 links.extend(base_rlinks)
145 links.extend(model_rlinks)
146
147 return links
148
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200149def xproto_base_links(m, table):
150 links = []
151
Sapan Bhatia3cfdf632017-06-08 05:14:03 +0200152 for base in m['bases']:
153 b = base['name']
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200154 if b in table:
155 base_links = xproto_base_links(table[b], table)
156
157 model_links = table[b]['links']
158 links.extend(base_links)
159 links.extend(model_links)
160 return links
161
Sapan Bhatiad022aeb2017-06-07 15:49:55 +0200162def xproto_string_type(xptags):
163 try:
164 max_length = eval(xptags['max_length'])
165 except:
166 max_length = 1024
167
168 if ('varchar' not in xptags):
169 return 'string'
170 else:
171 return 'text'
172
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700173def xproto_tuplify(nested_list_or_set):
174 if not isinstance(nested_list_or_set, list) and not isinstance(nested_list_or_set, set):
175 return nested_list_or_set
176 else:
177 return tuple([xproto_tuplify(i) for i in nested_list_or_set])
178
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700179def xproto_field_graph_components(fields, model, tag='unique_with'):
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700180 def find_components(graph):
181 pending = set(graph.keys())
182 components = []
183
184 while pending:
185 front = { pending.pop() }
186 component = set()
187
188 while front:
189 node = front.pop()
190 neighbours = graph[node]
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700191 neighbours -= component # These we have already visited
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700192 front |= neighbours
193
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700194 pending -= neighbours
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700195 component |= neighbours
196
197 components.append(component)
198
199 return components
200
201 field_graph = {}
202 field_names = {f['name'] for f in fields}
203
204 for f in fields:
205 try:
206 tagged_str = unquote(f['options'][tag])
207 tagged_fields = tagged_str.split(',')
208
209 for uf in tagged_fields:
210 if uf not in field_names:
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700211 raise FieldNotFound('Field "%s" not found in model "%s", referenced from field "%s" by option "%s"' % (uf, model['name'], f['name'], tag))
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700212
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700213 field_graph.setdefault(f['name'], set()).add(uf)
214 field_graph.setdefault(uf, set()).add(f['name'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700215 except KeyError:
216 pass
217
Matteo Scandoloa17e6e42018-05-25 10:28:25 -0700218 return find_components(field_graph)
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700219
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200220def xproto_api_opts(field):
221 options = []
222 if 'max_length' in field['options'] and field['type']=='string':
223 options.append('(val).maxLength = %s'%field['options']['max_length'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700224
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200225 try:
226 if field['options']['null'] == 'False':
227 options.append('(val).nonNull = true')
228 except KeyError:
229 pass
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700230
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200231 if 'link' in field and 'model' in field['options']:
232 options.append('(foreignKey).modelName = "%s"'%field['options']['model'])
Scott Bakerc4156c32017-12-08 10:58:21 -0800233 if ("options" in field) and ("port" in field["options"]):
234 options.append('(foreignKey).reverseFieldName = "%s"' % field['options']['port'])
Sapan Bhatiaf7934b52017-06-12 05:04:23 -0700235
Sapan Bhatiacb35e7f2017-05-24 12:17:28 +0200236 if options:
237 options_str = '[' + ', '.join(options) + ']'
238 else:
239 options_str = ''
240
241 return options_str
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700242
Matteo Scandolo431781c2017-09-06 15:33:07 -0700243def xproto_type_to_swagger_type(f):
244 try:
245 content_type = f['options']['content_type']
246 content_type = eval(content_type)
247 except:
248 content_type = None
249 pass
250
251 if 'choices' in f['options']:
252 return 'string'
253 elif content_type == 'date':
254 return 'string'
255 elif f['type'] == 'bool':
256 return 'boolean'
257 elif f['type'] == 'string':
258 return 'string'
259 elif f['type'] in ['int','uint32','int32'] or 'link' in f:
260 return 'integer'
261 elif f['type'] in ['double','float']:
262 return 'string'
263
264def xproto_field_to_swagger_enum(f):
265 if 'choices' in f['options']:
266 list = []
267
268 for c in eval(xproto_unquote(f['options']['choices'])):
269 list.append(c[0])
270
271 return list
272 else:
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800273 return False
Scott Bakera33ccb02018-01-26 13:03:28 -0800274
275def xproto_is_true(x):
276 # TODO: Audit xproto and make specification of trueness more uniform
277 if (x==True) or (x=="True") or (x=='"True"'):
278 return True
279 return False