update-documentation-conf 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python
  2. # documentation.conf update script
  3. #
  4. # Author: Paul Eggleton <paul.eggleton@linux.intel.com>
  5. #
  6. # Copyright (C) 2015 Intel Corporation
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License version 2 as
  10. # published by the Free Software Foundation.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. import sys
  21. import os
  22. import argparse
  23. import re
  24. from lxml import etree
  25. import logging
  26. def logger_create(name):
  27. logger = logging.getLogger(name)
  28. loggerhandler = logging.StreamHandler()
  29. loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
  30. logger.addHandler(loggerhandler)
  31. logger.setLevel(logging.INFO)
  32. return logger
  33. logger = logger_create('docconfupdater')
  34. def main():
  35. parser = argparse.ArgumentParser(description="documentation.conf updater")
  36. parser.add_argument('basepath', help='Path to OE-Core base directory')
  37. parser.add_argument('-q', '--quiet', help='Print only warnings/errors', action='store_true')
  38. args = parser.parse_args()
  39. if args.quiet:
  40. logger.setLevel(logging.WARN)
  41. if not os.path.isdir(args.basepath):
  42. logger.error('Specified base path %s not found')
  43. return 1
  44. doc_conf = os.path.join(args.basepath, 'meta', 'conf', 'documentation.conf')
  45. if not os.path.exists(doc_conf):
  46. logger.error('Unable to find %s' % doc_conf)
  47. return 1
  48. allowed_flags = ['doc']
  49. flag_re = re.compile(r'\[(.+?)\]')
  50. infos = {}
  51. tree = etree.parse('ref-manual/ref-variables.xml')
  52. root = tree.getroot()
  53. for glossary in root.findall('glossary'):
  54. for glossdiv in glossary.findall('glossdiv'):
  55. for glossentry in glossdiv.findall('glossentry'):
  56. info = glossentry.find('info')
  57. if info is not None:
  58. infoline = ' '.join(info.text.split())
  59. infolinesplit = infoline.split('=', 1)
  60. if len(infoline) < 2:
  61. logger.warn('Invalid info line (no = character), ignoring: %s' % infoline)
  62. continue
  63. flags = flag_re.findall(infolinesplit[0])
  64. if not flags:
  65. logger.warn('Invalid info line (no varflag), ignoring: %s' % infoline)
  66. continue
  67. for flag in flags:
  68. if flag not in allowed_flags:
  69. logger.warn('Invalid info line (varflag %s not in allowed list), ignoring: %s' % (flag, infoline))
  70. continue
  71. infos[infolinesplit[0].rstrip()] = infolinesplit[1].lstrip()
  72. if not infos:
  73. logger.error('ERROR: Unable to find any info tags in the glossary')
  74. return 1
  75. def sortkey(key):
  76. # Underscores sort undesirably, so replace them
  77. return key.split('[')[0].replace('_', '-')
  78. changed = False
  79. lines = []
  80. invars = False
  81. lastletter = None
  82. added = []
  83. with open(doc_conf, 'r') as dcf:
  84. for line in dcf:
  85. if not invars:
  86. if line.startswith('#') and 'DESCRIPTIONS FOR VARIABLES' in line:
  87. invars = True
  88. elif not line.startswith('#'):
  89. linesplit = line.split('=', 1)
  90. if len(linesplit) > 1:
  91. key = linesplit[0].rstrip()
  92. lastletter = key[0]
  93. # Find anything in the dict that should come before the current key
  94. for dkey in sorted(infos.keys()):
  95. if sortkey(dkey) < sortkey(key):
  96. lines.append('%s = %s\n' % (dkey, infos[dkey]))
  97. added.append(dkey)
  98. del infos[dkey]
  99. changed = True
  100. newvalue = infos.get(key, None)
  101. if newvalue:
  102. del infos[key]
  103. if newvalue != linesplit[1].strip():
  104. lines.append('%s = %s\n' % (key, newvalue))
  105. changed = True
  106. continue
  107. elif key in added:
  108. # We already added a new value for this key, so skip it
  109. continue
  110. elif lastletter:
  111. # Ensure we write out anything anything left over for this letter
  112. for dkey in sorted(infos.keys()):
  113. if dkey[0] == lastletter:
  114. lines.append('%s = %s\n' % (dkey, infos[dkey]))
  115. del infos[dkey]
  116. changed = True
  117. elif dkey[0] > lastletter:
  118. # List is sorted, so we're done
  119. break
  120. lastletter = None
  121. lines.append(line)
  122. if not invars:
  123. logger.error('ERROR: Unable to find variables section in documentation.conf')
  124. return 1
  125. if infos:
  126. changed = True
  127. # Write out anything left over
  128. lines.append('\n\n')
  129. for key in sorted(infos.keys()):
  130. lines.append('%s = %s\n' % (key, infos[key]))
  131. if changed:
  132. logger.info('Updating %s' % doc_conf)
  133. with open(doc_conf, 'w') as dcf:
  134. for line in lines:
  135. dcf.write(line)
  136. else:
  137. logger.info('No changes required')
  138. return 0
  139. if __name__ == "__main__":
  140. try:
  141. ret = main()
  142. except Exception:
  143. ret = 1
  144. import traceback
  145. traceback.print_exc(5)
  146. sys.exit(ret)