Created
October 22, 2013 18:45
-
-
Save bockel/7105913 to your computer and use it in GitHub Desktop.
Validates YAML and converts it to JSON.
Can also reverse the process and covert JSON back to YAML.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python | |
| """ | |
| Validates YAML and converts it to JSON. | |
| Can also reverse the process and covert JSON back to YAML. | |
| Intended to be used as a command line utility. | |
| Requirements: | |
| * Python >= 2.5 or >= 3.0 | |
| * PyYAML_ | |
| Example:: | |
| > python yaml2json.py file.yaml | |
| > cat file.yaml | python yaml2json.py - | |
| The ``-r`` or ``--reverse`` flag can be used to encode JSON as YAML:: | |
| > python yaml2json.py --reverse file.json | |
| It is also possible to roundtrip a YAML to JSON and back:: | |
| > python yaml2json.py file.yaml | python yaml2json.py -r - | |
| .. _PyYAML: http://pyyaml.org/ | |
| """ | |
| from __future__ import absolute_import | |
| from __future__ import print_function | |
| import json | |
| import sys | |
| from yaml import safe_load_all, safe_dump | |
| # fix the input function if in python2 | |
| if sys.version_info[0] < 3: | |
| input = raw_input | |
| error = lambda err: print(err, file=sys.stderr) | |
| def processor(decoder, encoder, fh, quiet=True): | |
| """ | |
| Decode and validate the filehandle, *fh*, using the decoder, *decoder*. | |
| Write the output to stdout using the encoder. | |
| Parameters: | |
| * **decoder**: a function that takes a filehandle and returns a list | |
| of decoded data representing the file contents. | |
| * **encoder**: a function that python data structure such as a | |
| dictionary, list, or string, and returns a string representing the | |
| encoded version of that data | |
| * **fh**: the filehandle of the file to decode | |
| * **quiet**: whether or not to print the encoded data | |
| Returns: | |
| A tuple of *(count, success)* with the number of documents | |
| attempted to decode and the number of those successfully | |
| decoded | |
| """ | |
| success = 0 | |
| count = 0 | |
| try: | |
| docs = decoder(fh) | |
| # print(docs) | |
| success += 1 | |
| count += len(docs) | |
| if not quiet or encoder is None: | |
| while True: | |
| try: | |
| d = docs.pop(0) | |
| except IndexError: | |
| break | |
| else: | |
| print(encoder(d, indent=4)) | |
| if len(docs) > 0: # or fcount < flen: | |
| input("Press Enter to continue...") | |
| except Exception as exc: | |
| if not quiet: | |
| error("Error: {0}".format(exc)) | |
| return (count, success) | |
| if __name__ == "__main__": | |
| from argparse import ArgumentParser | |
| from functools import partial | |
| parser = ArgumentParser( | |
| description="Validate and convert YAML docs to JSON" | |
| ) | |
| parser.add_argument('-q', '--quiet', action='store_true', default=False, | |
| help='Quiet. Only print validation status and errors') | |
| parser.add_argument('-r', '--reverse', action='store_true', default=False, | |
| help='Reverse the process: convert JSON to YAML') | |
| parser.add_argument('files', metavar='file', nargs='*', default='-', | |
| help='a YAML or JSON file (stdin: -)') | |
| args = parser.parse_args() | |
| count = 0 | |
| success = 0 | |
| flen = len(args.files) | |
| fcount = 0 | |
| decode_yaml = lambda yamldoc: [doc for doc in safe_load_all(yamldoc)] | |
| decode_json = lambda jsondoc: [json.load(jsondoc)] | |
| process = partial(processor, | |
| decode_json if args.reverse else decode_yaml, | |
| json.dumps if not args.reverse else safe_dump, | |
| quiet=args.quiet) | |
| for f in set(args.files): | |
| if f == '-': | |
| c, s = process(sys.stdin) | |
| else: | |
| with open(f) as fh: | |
| c, s = process(fh) | |
| count += c | |
| success += s | |
| if not args.quiet: | |
| error("Validated {0} of {1} files (found {2} streams)". | |
| format(success, flen, count)) | |
| # set the shell exit status: | |
| # 0 = success; | |
| # >0 = number of errors found | |
| sys.exit(flen - success) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment