def H_objectpath(ctx): infile, outfile = get_src_dest_defaults(ctx) data = load_data( ctx.opts.flags.input_format, infile, ctx ) assert data q = Tree(data) assert q.data o = q.execute( ctx.opts.args.expr ) if isinstance(o, types.GeneratorType): for s in o: v = stdout_data( s, ctx, outf=outfile ) if v: return v else: return stdout_data( o, ctx, outf=outfile )
def H_keys(ctx): "Output list of keys or indices" infile, outfile = get_src_dest_defaults(ctx) try: data = data_at_path(ctx, infile) except: return 1 if not data: return 1 if isinstance(data, dict): return stdout_data( data.keys(), ctx, outf=outfile ) elif isinstance(data, list): return stdout_data( range(0, len(data)), ctx, outf=outfile ) else: raise ValueError("Unhandled type %s" % type(data))
def H_update(ctx): "Update srcfile from stdin. Write to destfile or stdout. " if not ctx.opts.args.srcfiles: return updatefile = get_dest(ctx, 'r') data = load_data( ctx.opts.flags.output_format, updatefile, ctx ) updatefile.close() for cp in ctx.opts.flags.clear_paths: if cp.startswith('['): es = parse_json(cp) else: es = cp.split('/') cl = es.pop() v = data while es: el = es.pop(0) v = v[el] del v[cl] for src in ctx.opts.args.srcfiles: fmt = get_format_for_fileext(src) or ctx.opts.flags.input_format mdata = load_data( fmt, open_file( src, 'in', ctx=ctx ), ctx ) deep_update([data, mdata], ctx) updatefile = get_dest(ctx, 'w+') return stdout_data( data, ctx, outf=updatefile )
def H_merge(ctx, write=True): """ Merge srcfiles into last file. All srcfiles must be same format. Defaults to src-to-dest noop, iow. '- -' functions identical to 'dump'. """ if not ctx.opts.args.srcfiles and not ctx.opts.flags.line_input: ctx.opts.args.srcfile = '-' return H_dump(ctx, write=write) if ctx.opts.flags.line_input: ctx.opts.args.srcfile = ctx.opts.args.srcfiles.pop(0) set_format('input', 'src', ctx.opts) inp = open_file(ctx.opts.args.srcfile, 'in', ctx=ctx) ctx.opts.args.srcfiles += [ StringIO(line) for line in inp.readlines() ] else: ctx.opts.args.srcfile = ctx.opts.args.srcfiles[0] set_format('input', 'src', ctx.opts) if not (ctx.opts.flags.list_union or ctx.opts.flags.list_update): if ctx.opts.flags.list_update_nodict: ctx.opts.flags.list_update = True else: ctx.opts.flags.list_union = True data = None for srcfile in ctx.opts.args.srcfiles: mdata = None if hasattr(srcfile, 'read'): infile = srcfile elif isinstance(srcfile, (dict, list)): mdata = srcfile srcfile = '<inline>' infile = None else: infile = open_file(srcfile, defio='in', ctx=ctx) if infile and not mdata: mdata = load_data( ctx.opts.flags.input_format, infile, ctx ) if not data: data = type(mdata)() elif not isinstance(mdata, type(data)): raise ValueError( "Srcsfiles must have same root type. "\ "Expected %s, but found %s (%s)" % ( type(data), type(mdata), srcfile ) ) if isinstance(data, dict): deep_update([data, mdata], ctx) elif isinstance(data, list): data = deep_union([data, mdata], ctx) else: raise ValueError(data) if write: if not ctx.opts.flags.quiet: sys.stderr.write("Writing to %s\n" % ctx.opts.args.destfile) outfile = open_file(ctx.opts.args.destfile, mode='w+', ctx=ctx) return stdout_data( data, ctx, outf=outfile ) else: return data
def H_dump(ctx, write=True): "Read src and write destfile according to set i/o formats. " infile, outfile = get_src_dest_defaults(ctx) data = load_data( ctx.opts.flags.input_format, infile, ctx ) if write: return stdout_data( data, ctx, outf=outfile ) else: return data
def H_items(ctx): "Output for every key or item in object at path" infile, outfile = get_src_dest_defaults(ctx) try: data = data_at_path(ctx, infile) except: return 1 if not data: return 1 if isinstance(data, list): for item in data: stdout_data( item, ctx, outf=outfile ) elif isinstance(data, dict): for key, value in data.items(): subdata = { key: value } stdout_data( subdata, ctx, outf=outfile ) else: raise ValueError("Unhandled type %s" % type(data))
def H_append(ctx): "Add srcfiles as items to list. Optionally provide pathexpr to list. " if not ctx.opts.args.srcfiles: return appendfile = get_dest(ctx, 'r') data = l = load_data( ctx.opts.flags.output_format, appendfile, ctx ) if ctx.opts.args.pathexpr: l = data_at_path(ctx, None, data) for src in ctx.opts.args.srcfiles: fmt = get_format_for_fileext(src) or ctx.opts.flags.input_format mdata = load_data( fmt, open_file( src, 'in', ctx=ctx ), ctx ) l.append(mdata) updatefile = get_dest(ctx, 'w+') return stdout_data( data, ctx, outf=updatefile )
def H_path(ctx): """ Return data at path. Return 1 if path is not found. Use with ``--is-*`` opts to OR-test for type or exit 2. To check if a path could be inserted, use ``--is-new``. This overrules not-found errors, but only if the path could be inserted. When any existing element does not match a list or object type it also exits non-zero. """ infile, outfile = get_src_dest_defaults(ctx) data = None try: data = data_at_path(ctx, infile) infile.close() except (Exception) as err: if not ctx.opts.flags.is_new: if not ctx.opts.flags.quiet: tb = traceback.format_exc() sys.stderr.write(tb) sys.stderr.write("Error: getting %r: %r\n" % ( ctx.opts.args.pathexpr, err )) return 1 res = [ ] for tp in "new list obj int str bool".split(" "): if ctx.opts.flags["is_%s" % tp]: # FIXME: print(maptype(tp)) if tp == "new": infile, outfile = get_src_dest_defaults(ctx) if not data and data_check_path(ctx, infile): res += [ 0 ] elif isinstance(data, maptype(tp)): res += [ 0 ] else: res += [ 1 ] if res and min(res) == 0: res = [ 0 ] if not ctx.opts.flags.quiet: res += [ stdout_data( data, ctx, outf=outfile ) ] return max(res)
def H_update(ctx): "Update srcfile from stdin. Write to destfile or stdout. " if not ctx.opts.args.srcfiles: return updatefile = get_dest(ctx, 'r') data = load_data( ctx.opts.flags.output_format, updatefile, ctx ) updatefile.close() for src in ctx.opts.args.srcfiles: fmt = get_format_for_fileext(src) or ctx.opts.flags.input_format mdata = load_data( fmt, open_file( src, 'in', ctx=ctx ), ctx ) deep_update([data, mdata], ctx) updatefile = get_dest(ctx, 'w+') return stdout_data( ctx.opts.flags.output_format, data, updatefile, ctx )
def H_update_at(ctx): """Update object at path, using data read from srcfile(s)""" if not ctx.opts.args.srcfiles: return updatefile = get_dest(ctx, 'r') data = o = load_data( ctx.opts.flags.output_format, updatefile, ctx ) #if ctx.opts.args.pathexpr: #o = data_at_path(ctx, None, data) if ctx.opts.args.expr: q = Tree(data) assert q.data o = q.execute( ctx.opts.args.expr ) if isinstance(o, types.GeneratorType): r = list(o) assert len(r) == 1, r o = r[0] #r = [ stdout_data( s, ctx, outf=sys.stdout) for s in o ] #print(r) for src in ctx.opts.args.srcfiles: fmt = get_format_for_fileext(src) or ctx.opts.flags.input_format mdata = load_data( fmt, open_file( src, 'in', ctx=ctx ), ctx ) deep_update([o, mdata], ctx) updatefile = get_dest(ctx, 'w+') return stdout_data( data, ctx, outf=updatefile )
def H_from_flat_args(ctx): args = ctx.opts.args.fkv_args reader = FlatKVParser(rootkey=args[0]) reader.scan_kv_args(args) return stdout_data( reader.data, ctx )
def H_from_args(ctx): args = ctx.opts.args.kv_args reader = PathKVParser(rootkey=args[0]) reader.scan_kv_args(args) return stdout_data( ctx.opts.flags.output_format, reader.data, ctx.out, ctx )