blob: d71ea51af3eaec38f10c397203df860f3c3525bb [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15
Sapan Bhatia5ea307d2017-07-19 00:13:21 -040016from base import *
17import pdb
Sapan Bhatia1e021772017-08-19 02:15:48 -040018import re
Sapan Bhatia5ea307d2017-07-19 00:13:21 -040019
Zack Williams045b63d2019-01-22 16:30:57 -070020
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040021def django_content_type_string(xptags):
22 # Check possibility of KeyError in caller
Zack Williams045b63d2019-01-22 16:30:57 -070023 content_type = xptags["content_type"]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040024
25 try:
26 content_type = eval(content_type)
Zack Williams045b63d2019-01-22 16:30:57 -070027 except BaseException:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040028 pass
29
Zack Williams045b63d2019-01-22 16:30:57 -070030 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"
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040038 else:
Zack Williams045b63d2019-01-22 16:30:57 -070039 raise Exception("Unknown Type: %s" % content_type)
40
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040041
42def django_string_type(xptags):
43 try:
Zack Williams045b63d2019-01-22 16:30:57 -070044 max_length = eval(xptags["max_length"])
45 except BaseException:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040046 max_length = 1024 * 1024
47
Zack Williams045b63d2019-01-22 16:30:57 -070048 if "content_type" in xptags:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040049 return django_content_type_string(xptags)
Zack Williams045b63d2019-01-22 16:30:57 -070050 elif max_length < 1024 * 1024:
51 return "CharField"
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040052 else:
Zack Williams045b63d2019-01-22 16:30:57 -070053 return "TextField"
54
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040055
56def xproto_django_type(xptype, xptags):
Zack Williams045b63d2019-01-22 16:30:57 -070057 if xptype == "string":
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040058 return django_string_type(xptags)
Zack Williams045b63d2019-01-22 16:30:57 -070059 elif xptype == "float":
60 return "FloatField"
61 elif xptype == "bool":
62 return "BooleanField"
63 elif xptype == "uint32":
64 return "IntegerField"
65 elif xptype == "int32":
66 return "IntegerField"
67 elif xptype == "int64":
68 return "BigIntegerField"
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040069 else:
Zack Williams045b63d2019-01-22 16:30:57 -070070 raise Exception("Unknown Type: %s" % xptype)
71
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040072
73def xproto_django_link_type(f):
Zack Williams045b63d2019-01-22 16:30:57 -070074 if f["link_type"] == "manytoone":
75 return "ForeignKey"
76 elif f["link_type"] == "onetoone":
77 return "OneToOneField"
78 elif f["link_type"] == "manytomany":
79 if f["dst_port"]:
80 return "ManyToManyField"
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040081 else:
Zack Williams045b63d2019-01-22 16:30:57 -070082 return "GenericRelation"
83
Sapan Bhatiad8e4a232017-07-12 21:20:06 -040084
85def map_xproto_to_django(f):
Zack Williams045b63d2019-01-22 16:30:57 -070086 allowed_keys = [
87 "help_text",
88 "default",
89 "max_length",
90 "modifier",
91 "blank",
92 "choices",
93 "db_index",
94 "null",
95 "editable",
96 "on_delete",
97 "verbose_name",
98 "auto_now_add",
99 "unique",
100 "min_value",
101 "max_value",
102 ]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400103
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400104 # TODO evaluate if setting Null = False for all strings
Zack Williams045b63d2019-01-22 16:30:57 -0700105 m = {
106 "modifier": {"optional": True, "required": False, "_targets": ["null", "blank"]}
107 }
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400108 out = {}
109
Zack Williams045b63d2019-01-22 16:30:57 -0700110 for k, v in f["options"].items():
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400111 if k in allowed_keys:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400112 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700113 # NOTE this will be used to parse xproto optional/required field prefix
114 # and apply it to the null and blank fields
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400115 kv2 = m[k]
Zack Williams045b63d2019-01-22 16:30:57 -0700116 for t in kv2["_targets"]:
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400117 out[t] = kv2[v]
Zack Williams045b63d2019-01-22 16:30:57 -0700118 except BaseException:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400119 out[k] = v
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400120
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400121 return out
122
Zack Williams045b63d2019-01-22 16:30:57 -0700123
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400124def xproto_django_link_options_str(field, dport=None):
125 output_dict = map_xproto_to_django(field)
126
Zack Williams045b63d2019-01-22 16:30:57 -0700127 if dport and (dport == "+" or "+" not in dport):
128 output_dict["related_name"] = "%r" % dport
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400129
130 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700131 if field["through"]:
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400132 d = {}
Zack Williams045b63d2019-01-22 16:30:57 -0700133 if isinstance(field["through"], str):
134 split = field["through"].rsplit(".", 1)
135 d["name"] = split[-1]
136 if len(split) == 2:
137 d["package"] = split[0]
138 d["fqn"] = "package" + "." + d["name"]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400139 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700140 d["fqn"] = d["name"]
141 d["package"] = ""
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400142 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700143 d = field["through"]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400144
Zack Williams045b63d2019-01-22 16:30:57 -0700145 if not d["name"].endswith("_" + field["name"]):
146 output_dict["through"] = "%r" % d["fqn"]
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400147 except KeyError:
148 pass
149
150 return format_options_string(output_dict)
151
Zack Williams045b63d2019-01-22 16:30:57 -0700152
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400153def use_native_django_validators(k, v):
154
155 validators_map = {
Zack Williams045b63d2019-01-22 16:30:57 -0700156 "min_value": "MinValueValidator",
157 "max_value": "MaxValueValidator",
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400158 }
159
160 return "%s(%s)" % (validators_map[k], v)
161
Zack Williams045b63d2019-01-22 16:30:57 -0700162
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400163def format_options_string(d):
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400164
Zack Williams045b63d2019-01-22 16:30:57 -0700165 known_validators = ["min_value", "max_value"]
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400166 validator_lst = []
167
Zack Williams045b63d2019-01-22 16:30:57 -0700168 if not d:
169 return ""
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400170 else:
171
172 lst = []
Zack Williams045b63d2019-01-22 16:30:57 -0700173 for k, v in d.items():
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400174 if k in known_validators:
175 validator_lst.append(use_native_django_validators(k, v))
Zack Williams045b63d2019-01-22 16:30:57 -0700176 elif isinstance(v, str) and k == "default" and v.endswith('()"'):
177 lst.append("%s = %s" % (k, v[1:-3]))
178 elif isinstance(v, str) and v.startswith('"'):
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400179 try:
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400180 # unquote the value if necessary
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400181 tup = eval(v[1:-1])
Zack Williams045b63d2019-01-22 16:30:57 -0700182 if isinstance(tup, tuple):
183 lst.append("%s = %r" % (k, tup))
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400184 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700185 lst.append("%s = %s" % (k, v))
186 except BaseException:
187 lst.append("%s = %s" % (k, v))
188 elif isinstance(v, bool):
189 lst.append("%s = %r" % (k, bool(v)))
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400190 else:
191 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700192 lst.append("%s = %r" % (k, int(v)))
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400193 except ValueError:
Zack Williams045b63d2019-01-22 16:30:57 -0700194 lst.append("%s = %s" % (k, v))
195 validator_string = "validators=[%s]" % ", ".join(validator_lst)
196 option_string = ", ".join(lst)
Matteo Scandolo61a9f202018-08-01 08:58:13 -0400197 if len(validator_lst) == 0:
198 return option_string
199 elif len(lst) == 0:
200 return validator_string
201 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700202 return option_string + ", " + validator_string
203
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400204
205def xproto_django_options_str(field, dport=None):
206 output_dict = map_xproto_to_django(field)
207
Zack Williams045b63d2019-01-22 16:30:57 -0700208 if dport == "_":
209 dport = "+"
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400210
Zack Williams045b63d2019-01-22 16:30:57 -0700211 if dport and (dport == "+" or "+" not in dport):
212 output_dict["related_name"] = "%r" % dport
Sapan Bhatiad8e4a232017-07-12 21:20:06 -0400213
214 return format_options_string(output_dict)
Sapan Bhatia5ea307d2017-07-19 00:13:21 -0400215
Zack Williams045b63d2019-01-22 16:30:57 -0700216
Sapan Bhatia1e021772017-08-19 02:15:48 -0400217def xproto_camel_to_underscore(name):
Zack Williams045b63d2019-01-22 16:30:57 -0700218 return re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
219
Sapan Bhatia1e021772017-08-19 02:15:48 -0400220
Sapan Bhatia5ea307d2017-07-19 00:13:21 -0400221def xproto_validations(options):
222 try:
Zack Williams045b63d2019-01-22 16:30:57 -0700223 return [
224 map(str.strip, validation.split(":"))
225 for validation in unquote(options["validators"]).split(",")
226 ]
Sapan Bhatia5ea307d2017-07-19 00:13:21 -0400227 except KeyError:
228 return []
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800229
Zack Williams045b63d2019-01-22 16:30:57 -0700230
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800231def xproto_optioned_fields_to_list(fields, option, val):
232 """
233 List all the field that have a particural option
234 :param fields: (list) an array of message fields
235 :param option: (string) the option to look for
236 :param val: (any) the value of the option
237 :return: list of strings, field names where option is set
238 """
239
240 optioned_fields = []
241 for f in fields:
242 option_names = []
Zack Williams045b63d2019-01-22 16:30:57 -0700243 for k, v in f["options"].items():
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800244 option_names.append(k)
245
Zack Williams045b63d2019-01-22 16:30:57 -0700246 if option in option_names and f["options"][option] == val:
247 optioned_fields.append(f["name"])
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800248
249 return optioned_fields
250
Zack Williams045b63d2019-01-22 16:30:57 -0700251
Matteo Scandolo23cf15f2018-03-06 18:12:36 -0800252# TODO
253# - in modeldefs add info about this fields
254# - update the gui to have this fields as readonly