odml_convert.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. """odmlConvert
  2. odmlConvert searches for odML files within a provided SEARCHDIR
  3. and converts them to the newest odML format version.
  4. Original files will never be overwritten. New files will be
  5. written either to a new directory at the current or a specified
  6. location.
  7. Usage: odmlconvert [-r] [-o OUT] SEARCHDIR
  8. Arguments:
  9. SEARCHDIR Directory to search for odML files.
  10. Options:
  11. -o OUT Output directory. Must exist if specified.
  12. If not specified, output files will be
  13. written to the current directory.
  14. -r Search recursively. Directory structures
  15. will not be retained.
  16. -h --help Show this screen.
  17. --version Show version.
  18. """
  19. import os
  20. import pathlib
  21. import sys
  22. import tempfile
  23. from docopt import docopt
  24. try:
  25. from StringIO import StringIO
  26. except ImportError:
  27. from io import StringIO
  28. import odml
  29. from odml.tools.converters import VersionConverter as VerConf
  30. try:
  31. unicode = unicode
  32. except NameError:
  33. unicode = str
  34. def run_conversion(file_list, output_dir, report, source_format="XML"):
  35. """
  36. Convert a list of odML files to the latest odML version.
  37. :param file_list: list of files to be converted.
  38. :param output_dir: Directory where odML files converted to
  39. the latest odML version will be saved.
  40. :param report: Reporting StringIO.
  41. :param source_format: Original file format of the odML source files.
  42. XML, JSON and YAML are supported, default is XML.
  43. """
  44. # Exceptions are kept as broad as possible to ignore any non-odML or
  45. # invalid odML files and ensuring everything that can be will be converted.
  46. for curr_file in file_list:
  47. file_path = unicode(curr_file.absolute())
  48. report.write("[Info] Handling file '%s'\n" % file_path)
  49. # When loading the current file succeeds, it is
  50. # a recent odML format file and can be ignored.
  51. try:
  52. odml.load(file_path, source_format)
  53. report.write("[Info] Skip recent version file '%s'" % file_path)
  54. except Exception as exc:
  55. out_name = os.path.splitext(os.path.basename(file_path))[0]
  56. outfile = os.path.join(output_dir, "%s_conv.xml" % out_name)
  57. try:
  58. VerConf(file_path).write_to_file(outfile, source_format)
  59. except Exception as exc:
  60. # Ignore files we cannot parse or convert
  61. report.write("[Error] version converting file '%s': '%s'\n" %
  62. (file_path, exc))
  63. def main(args=None):
  64. """
  65. Convenience script to automatically convert odML files
  66. within a directory (tree) to the newest file version.
  67. Check the cli help for details.
  68. :param args: Command line arguments
  69. """
  70. parser = docopt(__doc__, argv=args, version="0.1.0")
  71. root = parser['SEARCHDIR']
  72. if not os.path.isdir(root):
  73. print(docopt(__doc__, "-h"))
  74. exit(1)
  75. # Handle all supported odML file formats.
  76. if parser['-r']:
  77. xfiles = list(pathlib.Path(root).rglob('*.odml'))
  78. xfiles.extend(list(pathlib.Path(root).rglob('*.xml')))
  79. jfiles = list(pathlib.Path(root).rglob('*.json'))
  80. yfiles = list(pathlib.Path(root).rglob('*.yaml'))
  81. else:
  82. xfiles = list(pathlib.Path(root).glob('*.odml'))
  83. xfiles.extend(list(pathlib.Path(root).glob('*.xml')))
  84. jfiles = list(pathlib.Path(root).glob('*.json'))
  85. yfiles = list(pathlib.Path(root).glob('*.yaml'))
  86. out_root = os.getcwd()
  87. if parser["-o"]:
  88. if not os.path.isdir(parser["-o"]):
  89. print("[Error] Could not find output directory '%s'" % parser["-o"])
  90. exit(1)
  91. out_root = parser["-o"]
  92. out_dir = tempfile.mkdtemp(prefix="odmlconv_", dir=out_root)
  93. # Use this monkeypatch reporter until there is a way
  94. # to run the converters silently.
  95. report = StringIO()
  96. report.write("[Info] Files will be saved to '%s'\n" % out_dir)
  97. run_conversion(xfiles, out_dir, report)
  98. run_conversion(jfiles, out_dir, report, "JSON")
  99. run_conversion(yfiles, out_dir, report, "YAML")
  100. print(report.getvalue())
  101. report.close()
  102. def dep_note(args=None):
  103. """
  104. Print deprecation warning and call main function.
  105. :param args: Command line arguments
  106. """
  107. print("\n[DEPRECATION WARNING] 'odmlconversion' will be removed with \n"
  108. "the next version release. Please use 'odmlconvert' instead.\n")
  109. main(args)
  110. if __name__ == "__main__":
  111. main(sys.argv[1:])