|
|
|
|
|
|
|
import sys |
|
import os.path |
|
import json |
|
import jsonpatch |
|
import tempfile |
|
import argparse |
|
|
|
|
|
parser = argparse.ArgumentParser( |
|
description='Apply a JSON patch on a JSON file') |
|
parser.add_argument('ORIGINAL', type=argparse.FileType('r'), |
|
help='Original file') |
|
parser.add_argument('PATCH', type=argparse.FileType('r'), |
|
nargs='?', default=sys.stdin, |
|
help='Patch file (read from stdin if omitted)') |
|
parser.add_argument('--indent', type=int, default=None, |
|
help='Indent output by n spaces') |
|
parser.add_argument('-b', '--backup', action='store_true', |
|
help='Back up ORIGINAL if modifying in-place') |
|
parser.add_argument('-i', '--in-place', action='store_true', |
|
help='Modify ORIGINAL in-place instead of to stdout') |
|
parser.add_argument('-v', '--version', action='version', |
|
version='%(prog)s ' + jsonpatch.__version__) |
|
parser.add_argument('-u', '--preserve-unicode', action='store_true', |
|
help='Output Unicode character as-is without using Code Point') |
|
|
|
def main(): |
|
try: |
|
patch_files() |
|
except KeyboardInterrupt: |
|
sys.exit(1) |
|
|
|
|
|
def patch_files(): |
|
""" Diffs two JSON files and prints a patch """ |
|
args = parser.parse_args() |
|
doc = json.load(args.ORIGINAL) |
|
patch = json.load(args.PATCH) |
|
result = jsonpatch.apply_patch(doc, patch) |
|
|
|
if args.in_place: |
|
dirname = os.path.abspath(os.path.dirname(args.ORIGINAL.name)) |
|
|
|
try: |
|
|
|
|
|
|
|
|
|
|
|
|
|
fd, pathname = tempfile.mkstemp(dir=dirname) |
|
fp = os.fdopen(fd, 'w') |
|
atomic = True |
|
|
|
except OSError: |
|
|
|
|
|
|
|
|
|
if args.backup: |
|
os.rename(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') |
|
fp = open(args.ORIGINAL.name, 'w') |
|
atomic = False |
|
|
|
else: |
|
|
|
|
|
|
|
fp = sys.stdout |
|
|
|
|
|
|
|
|
|
json.dump(result, fp, indent=args.indent, ensure_ascii=not(args.preserve_unicode)) |
|
fp.write('\n') |
|
|
|
if args.in_place: |
|
|
|
|
|
|
|
fp.close() |
|
|
|
if atomic: |
|
try: |
|
|
|
|
|
|
|
|
|
if args.backup: |
|
os.link(args.ORIGINAL.name, args.ORIGINAL.name + '.orig') |
|
os.chmod(pathname, os.stat(args.ORIGINAL.name).st_mode) |
|
os.rename(pathname, args.ORIGINAL.name) |
|
|
|
except OSError: |
|
|
|
|
|
|
|
|
|
os.unlink(args.ORIGINAL.name) |
|
os.rename(pathname, args.ORIGINAL.name) |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|