jj2.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (c) 2008-2014 Miki Tebeka <miki@mikitebeka.com>
  4. # All rights reserved.
  5. #
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are met:
  8. #
  9. # * Redistributions of source code must retain the above copyright notice, this
  10. # list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above copyright notice,
  12. # this list of conditions and the following disclaimer in the documentation
  13. # and/or other materials provided with the distribution.
  14. # * Neither the name of the "PythonWise" blog nor the names of its contributors
  15. # may be used to endorse or promote products derived from this software without
  16. # specific prior written permission.
  17. #
  18. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  22. # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  25. # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. '''Command line for expanding Jinja2 templates.
  29. Template variables can be passed either via the command line (using -vX=Y) or
  30. via a JSON/YAML configuration file (using -i /path/to/vars.json)
  31. Example:
  32. $ echo 'Hello {{name}}' > template.txt
  33. $ jj2.py -v name=Bugs template.txt
  34. Hello Bugs
  35. $
  36. '''
  37. import jinja2
  38. import json
  39. def load_vars(filename):
  40. with open(filename) as fo:
  41. if filename.lower().endswith('.json'):
  42. return json.load(fo)
  43. elif filename.lower().endswith('.yaml'):
  44. import yaml # Lazy import
  45. return yaml.load(fo)
  46. else:
  47. raise ValueError('unknown file type: {}'.format(filename))
  48. def parse_cmdline_vars(cmdline_vars):
  49. return dict(var.split('=', 1) for var in cmdline_vars)
  50. def main(argv=None):
  51. import sys
  52. from argparse import ArgumentParser, FileType
  53. argv = argv or sys.argv
  54. parser = ArgumentParser(description='Expand Jinja2 template')
  55. parser.add_argument('template', help='template file to expand',
  56. type=FileType('r'), nargs='?', default=sys.stdin)
  57. parser.add_argument('--var', '-v', action='append',
  58. help='template variables (in X=Y format)')
  59. parser.add_argument('--output', '-o', help='output file',
  60. type=FileType('w'), nargs='?', default=sys.stdout)
  61. parser.add_argument('--vars-file', '-i', help='vars files (YAML or JSON)',
  62. nargs='?')
  63. args = parser.parse_args(argv[1:])
  64. tvars = {}
  65. if args.vars_file:
  66. tvars.update(load_vars(args.vars_file))
  67. tvars.update(parse_cmdline_vars(args.var or []))
  68. # Fail on undefined
  69. env = jinja2.Environment(undefined=jinja2.StrictUndefined, loader=jinja2.FileSystemLoader('.'))
  70. template = env.from_string(args.template.read())
  71. args.output.write(template.render(tvars))
  72. if __name__ == '__main__':
  73. main()