blob: 64ab51ac8913c6898b4a52309f288706a451bea3 [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 Bhatia5ea307d2017-07-19 00:13:21 -040017from base import *
18import pdb
Sapan Bhatia1e021772017-08-19 02:15:48 -040019import re
Sapan Bhatia5ea307d2017-07-19 00:13:21 -040020
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040021def django_content_type_string(xptags):
22 # Check possibility of KeyError in caller
23 content_type = xptags['content_type']
24
25 try:
26 content_type = eval(content_type)
27 except:
28 pass
29
30 if (content_type=='url'):
31 return 'URLField'
32 if (content_type=='date'):
33 return 'DateTimeField'
34 elif (content_type=='ip'):
35 return 'GenericIPAddressField'
36 elif (content_type=='stripped' or content_type=='"stripped"'):
37 return 'StrippedCharField'
38 else:
39 raise Exception('Unknown Type: %s'%content_type)
40
41def django_string_type(xptags):
42 try:
43 max_length = eval(xptags['max_length'])
44 except:
45 max_length = 1024 * 1024
46
47 if ('content_type' in xptags):
48 return django_content_type_string(xptags)
49 elif (max_length<1024*1024):
50 return 'CharField'
51 else:
52 return 'TextField'
53
54def xproto_django_type(xptype, xptags):
55 if (xptype=='string'):
56 return django_string_type(xptags)
57 elif (xptype=='float'):
58 return 'FloatField'
59 elif (xptype=='bool'):
60 return 'BooleanField'
61 elif (xptype=='uint32'):
62 return 'IntegerField'
63 elif (xptype=='int32'):
64 return 'IntegerField'
65 elif (xptype=='int64'):
66 return 'BigIntegerField'
67 else:
68 raise Exception('Unknown Type: %s'%xptype)
69
70def xproto_django_link_type(f):
71 if (f['link_type']=='manytoone'):
72 return 'ForeignKey'
Sapan Bhatia9590a882017-08-01 08:35:23 -040073 elif (f['link_type']=='onetoone'):
74 return 'OneToOneField'
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040075 elif (f['link_type']=='manytomany'):
76 if (f['dst_port']):
77 return 'ManyToManyField'
78 else:
79 return 'GenericRelation'
80
81def map_xproto_to_django(f):
Matteo Scandolo61a9f202018-08-01 08:58:13 -040082 allowed_keys=['help_text','default','max_length','modifier','blank','choices','db_index','null','editable','on_delete','verbose_name', 'auto_now_add', 'unique', 'min_value', 'max_value']
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040083
Matteo Scandolo61a9f202018-08-01 08:58:13 -040084 # TODO evaluate if setting Null = False for all strings
85 m = {'modifier':{'optional':True, 'required':False, '_targets': ['null', 'blank']}}
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040086 out = {}
87
88 for k,v in f['options'].items():
Matteo Scandolo61a9f202018-08-01 08:58:13 -040089 if k in allowed_keys:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040090 try:
Matteo Scandolo61a9f202018-08-01 08:58:13 -040091 # NOTE this will be used to parse xproto optional/required field prefix and apply it to the null and blank fields
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040092 kv2 = m[k]
Matteo Scandolo61a9f202018-08-01 08:58:13 -040093 for t in kv2['_targets']:
94 out[t] = kv2[v]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040095 except:
96 out[k] = v
Matteo Scandolo61a9f202018-08-01 08:58:13 -040097
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040098 return out
99
100def xproto_django_link_options_str(field, dport=None):
101 output_dict = map_xproto_to_django(field)
102
103 if (dport and (dport=='+' or '+' not in dport)):
104 output_dict['related_name'] = '%r'%dport
105
106 try:
107 if field['through']:
108 d = {}
109 if isinstance(field['through'], str):
110 split = field['through'].rsplit('.',1)
111 d['name'] = split[-1]
112 if len(split)==2:
113 d['package'] = split[0]
114 d['fqn'] = 'package' + '.' + d['name']
115 else:
116 d['fqn'] = d['name']
117 d['package'] = ''
118 else:
119 d = field['through']
120
121 if not d['name'].endswith('_'+field['name']):
122 output_dict['through'] = '%r'%d['fqn']
123 except KeyError:
124 pass
125
126 return format_options_string(output_dict)
127
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400128def use_native_django_validators(k, v):
129
130 validators_map = {
131 'min_value': 'MinValueValidator',
132 'max_value': 'MaxValueValidator'
133 }
134
135 return "%s(%s)" % (validators_map[k], v)
136
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400137def format_options_string(d):
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400138
139 known_validators = ['min_value', 'max_value']
140 validator_lst = []
141
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400142 if (not d):
143 return ''
144 else:
145
146 lst = []
147 for k,v in d.items():
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400148 if k in known_validators:
149 validator_lst.append(use_native_django_validators(k, v))
150 elif (type(v)==str and k=='default' and v.endswith('()"')):
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400151 lst.append('%s = %s'%(k,v[1:-3]))
152 elif (type(v)==str and v.startswith('"')):
153 try:
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400154 # unquote the value if necessary
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400155 tup = eval(v[1:-1])
156 if (type(tup)==tuple):
157 lst.append('%s = %r'%(k,tup))
158 else:
159 lst.append('%s = %s'%(k,v))
160 except:
161 lst.append('%s = %s'%(k,v))
162 elif (type(v)==bool):
163 lst.append('%s = %r'%(k,bool(v)))
164 else:
165 try:
166 lst.append('%s = %r'%(k,int(v)))
167 except ValueError:
168 lst.append('%s = %s'%(k,v))
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400169 validator_string = "validators=[%s]" % ', '.join(validator_lst)
170 option_string = ', '.join(lst)
171 if len(validator_lst) == 0:
172 return option_string
173 elif len(lst) == 0:
174 return validator_string
175 else:
176 return option_string + ", " + validator_string
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400177
178def xproto_django_options_str(field, dport=None):
179 output_dict = map_xproto_to_django(field)
180
181 if (dport=='_'):
182 dport = '+'
183
184 if (dport and (dport=='+' or '+' not in dport)):
185 output_dict['related_name'] = '%r'%dport
186
187 return format_options_string(output_dict)
Sapan Bhatia5ea307d2017-07-19 00:13:21 -0400188
Sapan Bhatia1e021772017-08-19 02:15:48 -0400189def xproto_camel_to_underscore(name):
190 return re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
191
Sapan Bhatia5ea307d2017-07-19 00:13:21 -0400192def xproto_validations(options):
193 try:
194 return [map(str.strip, validation.split(':')) for validation in unquote(options['validators']).split(',')]
195 except KeyError:
196 return []
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800197
198def xproto_optioned_fields_to_list(fields, option, val):
199 """
200 List all the field that have a particural option
201 :param fields: (list) an array of message fields
202 :param option: (string) the option to look for
203 :param val: (any) the value of the option
204 :return: list of strings, field names where option is set
205 """
206
207 optioned_fields = []
208 for f in fields:
209 option_names = []
210 for k, v in f['options'].items():
211 option_names.append(k)
212
213 if option in option_names and f['options'][option] == val:
214 optioned_fields.append(f['name'])
215
216 return optioned_fields
217
218# TODO
219# - in modeldefs add info about this fields
220# - update the gui to have this fields as readonly