Skip to content

Commit da22e6d

Browse files
committed
net: scripts: Convert yaml config script to support jsonschema
As pykwalify is no longer used in zephyr, the yaml schema format is changed to jsonschema format. This requires changes to python script that generates C struct configuration definitions. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent c110832 commit da22e6d

File tree

1 file changed

+72
-28
lines changed

1 file changed

+72
-28
lines changed

scripts/net/net-yaml-config.py

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -196,18 +196,37 @@ def create_yaml_file():
196196

197197
# If user has supplied an argument, treat it as a schema file
198198
if bool(data) and len(sys.argv[1:]) > 0:
199-
# If pykwalify is installed, then validate the yaml
199+
# If jsonschema is installed, then validate the yaml
200200
try:
201-
import pykwalify.core
201+
import jsonschema
202202

203203
def yaml_validate(data, schema):
204204
if not schema:
205205
return
206-
c = pykwalify.core.Core(source_data=data, schema_files=[schema])
207-
c.validate(raise_exception=True)
206+
207+
try:
208+
from yaml import CSafeLoader as SafeLoader
209+
except ImportError:
210+
from yaml import SafeLoader
211+
212+
with open(schema) as f:
213+
net_schema = yaml.load(f.read(), Loader=SafeLoader)
214+
215+
validator_class = jsonschema.validators.validator_for(net_schema)
216+
validator_class.check_schema(net_schema)
217+
validator = validator_class(net_schema)
218+
219+
errors = sorted(validator.iter_errors(data), key=lambda e: e.path)
220+
if errors:
221+
# Build a readable message with each error and its path
222+
lines = []
223+
for e in errors:
224+
path = ".".join(map(str, list(e.path))) or "<root>"
225+
lines.append(f"{path}: {e.message}")
226+
raise jsonschema.ValidationError("\n".join(lines))
208227

209228
except ImportError as e:
210-
sys.stderr.write("can't import pykwalify; won't validate YAML (%s)", e)
229+
sys.stderr.write("can't import jsonschema; won't validate YAML (%s)", e)
211230

212231
def yaml_validate(data, schema):
213232
pass
@@ -267,7 +286,7 @@ def walk_list(lst, indent):
267286
elif isinstance(v, dict):
268287
walk_dict(v, "\t" + indent)
269288
elif isinstance(v, str):
270-
print(indent + "\t" + "\"" + v + "\",")
289+
print(indent + "\t" + ".value = \"" + v + "\",")
271290
elif isinstance(v, bool):
272291
print(indent + "\t" + str(v).lower() + ",")
273292
elif isinstance(v, int):
@@ -310,35 +329,67 @@ def output(indent, str):
310329

311330
def walk_dict_schema(level, top_level_name, cdict, key_upper, map, indent):
312331
global changed
332+
str_val = ""
333+
313334
for key, value in map.items():
314335
if key == "type":
315-
if value == "str":
316-
output(indent, "const char *" + key_upper + ";")
336+
# Use value instead of items to avoid changing too many places in C code
337+
if key_upper == "items":
338+
key_upper = "value"
339+
340+
if value == "string":
341+
str_val = "const char *" + key_upper + ";"
317342
changed += indent + "bool " + "__" + key_upper + "_changed : 1;" + "\n"
318-
elif value == "bool":
343+
elif value == "boolean":
319344
output(indent, "bool " + key_upper + ";")
320345
changed += indent + "bool " + "__" + key_upper + "_changed : 1;" + "\n"
321-
elif value == "int":
346+
elif value == "integer":
322347
output(indent, "int " + key_upper + ";")
323348
changed += indent + "bool " + "__" + key_upper + "_changed : 1;" + "\n"
324-
elif value == "seq":
349+
elif value == "array":
325350
print(changed, end="")
326351
changed = ""
327352
output(indent, "struct " + top_level_name + "_" + key_upper + " {")
328-
elif value == "map":
353+
elif value == "object":
329354
print(changed, end="")
330355
changed = ""
331356
if key_upper != "value":
332357
if level == 1:
333358
output(indent, "struct " + key_upper + " {")
334359
else:
335360
output(indent, "struct " + top_level_name + "_" + key_upper + " {")
336-
elif value == "any" and key_upper == "bind_to":
337-
output(indent, "int bind_to;")
338-
changed += indent + "bool " + "__bind_to_changed : 1;" + "\n"
339361
continue
340-
elif key == "mapping":
362+
363+
if key == "bind_to":
364+
output(indent + "\t", "int bind_to;")
365+
changed += indent + "\t" + "bool " + "__bind_to_changed : 1;" + "\n"
366+
continue
367+
368+
if key == "maxLength":
369+
output(indent, "char " + key_upper + "[" + str(value) + "];")
370+
str_val = ""
371+
continue
372+
373+
# Print the string as a pointer if it is set without maxLength
374+
if len(str_val) > 0:
375+
output(indent, str_val)
376+
str_val = ""
377+
continue
378+
379+
if isinstance(value, dict):
341380
walk_dict_schema(level + 1, top_level_name, cdict, key, value, "\t" + indent)
381+
elif isinstance(value, list):
382+
walk_list_schema(level + 1, top_level_name, cdict, key, value, "\t" + indent)
383+
384+
if key == "items":
385+
print(changed, end="")
386+
changed = ""
387+
if key_upper in combined_data:
388+
output(indent, "} " + key_upper + "[" + str(combined_data[key_upper]) + "];")
389+
else:
390+
output(indent, "} " + key_upper + "[1];")
391+
392+
elif key == "properties":
342393
print(changed, end="")
343394
changed = ""
344395
if key_upper != "value":
@@ -348,19 +399,10 @@ def walk_dict_schema(level, top_level_name, cdict, key_upper, map, indent):
348399
output(indent, "};")
349400
else:
350401
output(indent, "} " + key_upper + ";")
351-
continue
352-
elif key == "sequence":
353-
walk_list_schema(level + 1, top_level_name, cdict, "value", value, "\t" + indent)
354-
print(changed, end="")
355-
changed = ""
356-
if key_upper in combined_data:
357-
output(indent, "} " + key_upper + "[" + str(combined_data[key_upper]) + "];")
358-
else:
359-
output(indent, "} " + key_upper + "[1];")
360-
continue
361402

362-
if isinstance(value, dict):
363-
walk_dict_schema(level + 1, top_level_name, cdict, key, value, indent)
403+
# Print the string as a pointer if it is set without maxLength
404+
if len(str_val) > 0:
405+
output(indent, str_val)
364406

365407

366408
def walk_list_schema(level, top_level_name, cdict, key, lst, indent):
@@ -385,6 +427,8 @@ def walk_list_schema(level, top_level_name, cdict, key, lst, indent):
385427
# Create C struct definition. Prefix some of the generated C struct fields with
386428
# by the name of the struct to make them unambiguous.
387429
for key, value in schema.items():
430+
if key in ('$id', '$schema', 'title', 'description'):
431+
print("/* " + key + ": " + str(value) + " */")
388432
if isinstance(value, dict):
389433
walk_dict_schema(0, list(data.keys())[0], schema_data, key, value, "")
390434

0 commit comments

Comments
 (0)