generate.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from collections import OrderedDict
  2. from ruamel import yaml
  3. INDENT = 4
  4. def write_configuration(config_filename, config):
  5. '''
  6. Given a target config filename and a config data structure of nested OrderedDicts, write out the
  7. config to file as YAML.
  8. '''
  9. with open(config_filename, 'w') as config_file:
  10. config_file.write(yaml.round_trip_dump(config, indent=INDENT, block_seq_indent=INDENT))
  11. def _insert_newline_before_comment(config, field_name):
  12. '''
  13. Using some ruamel.yaml black magic, insert a blank line in the config right befor the given
  14. field and its comments.
  15. '''
  16. config.ca.items[field_name][1].insert(
  17. 0,
  18. yaml.tokens.CommentToken('\n', yaml.error.CommentMark(0), None),
  19. )
  20. def add_comments_to_configuration(config, schema, indent=0):
  21. '''
  22. Using descriptions from a schema as a source, add those descriptions as comments to the given
  23. config before each field. This function only adds comments for the top-most config map level.
  24. Indent the comment the given number of characters.
  25. '''
  26. for index, field_name in enumerate(config.keys()):
  27. field_schema = schema['map'].get(field_name, {})
  28. description = field_schema.get('desc')
  29. # No description to use? Skip it.
  30. if not schema or not description:
  31. continue
  32. config.yaml_set_comment_before_after_key(
  33. key=field_name,
  34. before=description,
  35. indent=indent,
  36. )
  37. if index > 0:
  38. _insert_newline_before_comment(config, field_name)
  39. def _section_schema_to_sample_configuration(section_schema):
  40. '''
  41. Given the schema for a particular config section, generate and return sample config for that
  42. section. Include comments for each field based on the schema "desc" description.
  43. '''
  44. section_config = yaml.comments.CommentedMap([
  45. (field_name, field_schema['example'])
  46. for field_name, field_schema in section_schema['map'].items()
  47. ])
  48. add_comments_to_configuration(section_config, section_schema, indent=INDENT)
  49. return section_config
  50. def _schema_to_sample_configuration(schema):
  51. '''
  52. Given a loaded configuration schema, generate and return sample config for it. Include comments
  53. for each section based on the schema "desc" description.
  54. '''
  55. config = yaml.comments.CommentedMap([
  56. (section_name, _section_schema_to_sample_configuration(section_schema))
  57. for section_name, section_schema in schema['map'].items()
  58. ])
  59. add_comments_to_configuration(config, schema)
  60. return config
  61. def generate_sample_configuration(config_filename, schema_filename):
  62. '''
  63. Given a target config filename and the path to a schema filename in pykwalify YAML schema
  64. format, write out a sample configuration file based on that schema.
  65. '''
  66. schema = yaml.round_trip_load(open(schema_filename))
  67. config = _schema_to_sample_configuration(schema)
  68. write_configuration(config_filename, config)