Skip to content

Commit

Permalink
Release 0.1.0 (#4)
Browse files Browse the repository at this point in the history
* Support custom indent/tabs
* Support the -n arg
* Additional tests
* Remove unneeded property, add additional specs, fix null input long arg
* Fix it block text
* Remove XML from supported input formats
  • Loading branch information
Blacksmoke16 authored Jul 7, 2019
1 parent ee4d9ce commit e5fa156
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 52 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Built with Crystal](https://img.shields.io/badge/built%20with-crystal-000000.svg?style=flat-square)](https://crystal-lang.org/)
[![Build Status](https://travis-ci.org/Blacksmoke16/oq.svg?branch=master)](https://travis-ci.org/Blacksmoke16/oq)
[![Latest release](https://img.shields.io/github/release/Blacksmoke16/oq.svg?style=flat-square)](https://github.com/Blacksmoke16/oq/releases)
[![Snap Status](https://build.snapcraft.io/badge/Blacksmoke16/oq.svg)](https://build.snapcraft.io/user/Blacksmoke16/oq)
[![oq](https://snapcraft.io/omni-q/badge.svg)](https://snapcraft.io/omni-q)

A performant, portable `jq` wrapper thats facilitates the consumption and output of formats other than JSON; using `jq` filters to transform the data.

Expand Down Expand Up @@ -33,7 +33,7 @@ Usage: oq [--help] [oq-arguments] [jq-arguments] jq_filter [file [files...]]
--help Show this help message.
-i FORMAT, --input FORMAT Format of the input data. Supported formats: json, yaml, xml.
-o FORMAT, --output FORMAT Format of the output data. Supported formats: json, yaml, xml.
--xml-root=ROOT Name of the root XML element if converting to XML.
--xml-root ROOT Name of the root XML element if converting to XML.
```
## Roadmap
Expand Down
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: omni-q
name: oq

description: |
A performant, and portable jq wrapper thats facilitates the consumption and output of formats other than JSON; using jq filters to transform the data.
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ summary: A performant, and portable jq wrapper to support formats other than JSO
description: |
A performant, and portable jq wrapper thats facilitates the consumption and output of formats other than JSON; using jq filters to transform the data.
grade: devel
grade: stable
confinement: strict
base: core18

Expand Down
113 changes: 93 additions & 20 deletions spec/oq_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,56 +12,56 @@ JSON

describe Oq do
describe "when given a filter file" do
it "returns the correct output" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: ["-f", "spec/assets/test_filter"]) do |output|
output.should eq "\"Jim\"\n"
output.should eq %("Jim"\n)
end
end
end

describe "with a simple filter" do
it "returns the correct output" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: [".name"]) do |output|
output.should eq "\"Jim\"\n"
output.should eq %("Jim"\n)
end
end
end

describe "with a filter to get nested values" do
it "returns the correct output" do
it "should return the correct output" do
run_binary(input: NESTED_JSON_OBJECT, args: [".foo.bar.baz"]) do |output|
output.should eq "5\n"
end
end
end

describe "with a filter to get nested values and YAML input" do
it "returns the correct output" do
run_binary(input: "---\nfoo:\n bar:\n baz: 5", args: [".foo.bar.baz", "-i", "yaml"]) do |output|
it "should return the correct output" do
run_binary(input: "---\nfoo:\n bar:\n baz: 5", args: ["-i", "yaml", ".foo.bar.baz"]) do |output|
output.should eq "5\n"
end
end
end

describe "with YAML output" do
it "should return the correct output" do
run_binary(input: NESTED_JSON_OBJECT, args: [".", "-o", "yaml"]) do |output|
run_binary(input: NESTED_JSON_OBJECT, args: ["-o", "yaml", "."]) do |output|
output.should eq "---\nfoo:\n bar:\n baz: 5\n"
end
end
end

describe "with XML output" do
it "should return the correct output" do
run_binary(input: NESTED_JSON_OBJECT, args: [".", "-o", "xml"]) do |output|
run_binary(input: NESTED_JSON_OBJECT, args: ["-o", "xml", "."]) do |output|
output.should eq "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n <foo>\n <bar>\n <baz>5</baz>\n </bar>\n </foo>\n</root>\n"
end
end
end

describe "with YAML input" do
it "should return the correct output" do
run_binary(input: "---\nfoo:\n bar:\n baz: 5\n", args: [".", "-c", "-i", "yaml"]) do |output|
run_binary(input: "---\nfoo:\n bar:\n baz: 5\n", args: ["-c", "-i", "yaml", "."]) do |output|
output.should eq "#{NESTED_JSON_OBJECT}\n"
end
end
Expand All @@ -77,63 +77,63 @@ describe Oq do

describe "with multiple JSON file input" do
it "should return the correct output" do
run_binary(input: "", args: [".", "-c", "spec/assets/data1.json", "spec/assets/data2.json"]) do |output|
run_binary(input: "", args: ["-c", ".", "spec/assets/data1.json", "spec/assets/data2.json"]) do |output|
output.should eq %({"name":"Jim"}\n{"name":"Bob"}\n)
end
end
end

describe "with multiple JSON file input and slurp" do
it "should return the correct output" do
run_binary(input: "", args: [".", "-c", "--slurp", "spec/assets/data1.json", "spec/assets/data2.json"]) do |output|
run_binary(input: "", args: ["-c", "--slurp", ".", "spec/assets/data1.json", "spec/assets/data2.json"]) do |output|
output.should eq %([{"name":"Jim"},{"name":"Bob"}]\n)
end
end
end

describe "with multiple YAML file input" do
it "should return the correct output" do
run_binary(input: "", args: [".", "-c", "-i", "yaml", "spec/assets/data1.yml", "spec/assets/data2.yml"]) do |output|
run_binary(input: "", args: ["-c", "-i", "yaml", ".", "spec/assets/data1.yml", "spec/assets/data2.yml"]) do |output|
output.should eq %({"name":"Jim"}\n{"age":17}\n)
end
end
end

describe "with multiple YAML file input and slurp" do
it "should return the correct output" do
run_binary(input: "", args: [".", "-c", "-i", "yaml", "-s", "spec/assets/data1.yml", "spec/assets/data2.yml"]) do |output|
run_binary(input: "", args: ["-c", "-i", "yaml", "-s", ".", "spec/assets/data1.yml", "spec/assets/data2.yml"]) do |output|
output.should eq %([{"name":"Jim"},{"age":17}]\n)
end
end
end

describe "with STDIN YAML input and slurp" do
it "should return the correct output" do
run_binary(input: "---\nname: Jim", args: [".", "-c", "-i", "yaml", "-s"]) do |output|
run_binary(input: "---\nname: Jim", args: ["-c", "-i", "yaml", "-s", "."]) do |output|
output.should eq %([{"name":"Jim"}]\n)
end
end
end

describe "with YAML input and XML output" do
it "should convert between formats" do
run_binary(input: "---\nfoo:\n bar:\n baz: 5\n", args: [".", "-i", "yaml", "-o", "xml"]) do |output|
run_binary(input: "---\nfoo:\n bar:\n baz: 5\n", args: ["-i", "yaml", "-o", "xml", "."]) do |output|
output.should eq "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n <foo>\n <bar>\n <baz>5</baz>\n </bar>\n </foo>\n</root>\n"
end
end
end

describe "with raw output" do
it "should return the correct output" do
run_binary(input: "", args: [".", "-R", "-o", "yaml", "spec/assets/data1.json"]) do |output|
run_binary(input: "", args: ["-R", "-o", "yaml", ".", "spec/assets/data1.json"]) do |output|
output.should eq %(--- '{"name": "Jim"}'\n)
end
end
end

describe "with the -c options" do
it "should compact the output" do
run_binary(input: NESTED_JSON_OBJECT, args: [".", "-c"]) do |output|
it "should return the correct output" do
run_binary(input: NESTED_JSON_OBJECT, args: ["-c", "."]) do |output|
output.should eq %({"foo":{"bar":{"baz":5}}}\n)
end
end
Expand All @@ -147,10 +147,83 @@ describe Oq do
end
end

describe "with null input option" do
describe "with a scalar value" do
it "should return the correct output" do
run_binary(input: nil, args: ["-n", "0"]) do |output|
output.should eq "0\n"
end
end

it "should return the correct output" do
run_binary(input: nil, args: ["--null-input", "0"]) do |output|
output.should eq "0\n"
end
end
end

describe "with a JSON object string" do
it "should return the correct output" do
run_binary(input: nil, args: ["-cn", %([{"foo":"bar"},{"foo":"baz"}])]) do |output|
output.should eq %([{"foo":"bar"},{"foo":"baz"}]\n)
end
end
end

describe "with input from STDIN" do
it "should return the correct output" do
run_binary(input: "foo", args: ["-n"]) do |output|
output.should eq "null\n"
end
end
end
end

describe "with a custom indent value with JSON" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: ["--indent", "1", "."]) do |output|
output.should eq %({\n "name": "Jim"\n}\n)
end
end
end

describe "with the --tab option" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: ["--tab", "."]) do |output|
output.should eq %({\n\t"name": "Jim"\n}\n)
end
end
end

describe "with a custom indent value with XML" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: ["--indent", "3", "-o", "xml", "."]) do |output|
output.should eq "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\n <name>Jim</name>\n</root>\n"
end
end
end

describe "with a custom XML root" do
it "should return the correct output" do
run_binary(input: SIMPLE_JSON_OBJECT, args: ["--xml-root", "friends", "-o", "xml", "."]) do |output|
output.should eq "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<friends>\n <name>Jim</name>\n</friends>\n"
end
end
end

describe "when streaming input" do
it "should return the correct output" do
run_binary(input: %({"a": [1, 2.2, true, "abc", null]}), args: ["-nc", "--stream", "fromstream( 1|truncate_stream(inputs) | select(length>1) | .[0] |= .[1:] )"]) do |output|
output.should eq %(1\n2.2\ntrue\n"abc"\nnull\n)
end
end
end

describe "with XML input" do
it "should return not implemented" do
run_binary(input: "", args: [".", "-i", "xml"]) do |output|
run_binary(input: "", args: ["-i", "xml", "."]) do |output, status|
output.should eq "Not Implemented\n"
status.exit_code.should eq 1
end
end
end
Expand Down
11 changes: 5 additions & 6 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ def assert_builder_output(expected : String, &block : XML::Builder -> Nil) : Nil
end

# Runs the the binary with the given *name* and *args*.
def run_binary(input : String, name : String = "bin/oq", args : Array(String) = [] of String, &block : String -> Nil)
def run_binary(input : String?, name : String = "bin/oq", args : Array(String) = [] of String, &block : String, Process::Status -> Nil)
buffer = IO::Memory.new
input = IO::Memory.new input
Process.run(name, args, error: buffer, output: buffer, input: input)
yield buffer.to_s
buffer.close
input.close
in = IO::Memory.new
in << input if input
status = Process.run(name, args, error: buffer, output: buffer, input: in.rewind)
yield buffer.to_s, status
end
16 changes: 16 additions & 0 deletions spec/to_xml_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ describe "#to_xml" do
end
end

describe "with multiple attribute objects" do
it "should convert correctly" do
assert_builder_output("<name>Jim</name><age unit=\"years\" some_key=\"-1\">12</age>") do |b|
{"name" => "Jim", "age" => {"@unit" => "years", "@some_key" => -1, "#text" => 12}}.to_xml b
end
end
end

describe "with a nested attribute object" do
it "should convert correctly" do
assert_builder_output("<name>Jim</name><age><unit>years</unit>12</age>") do |b|
Expand Down Expand Up @@ -179,5 +187,13 @@ describe "#to_xml" do
end
end
end

describe "with multiple attribute objects" do
it "should convert correctly" do
assert_builder_output("<name>Jim</name><age unit=\"years\" some_key=\"-1\">12</age>") do |b|
{"name": "Jim", "age": {"@unit": "years", "@some_key": -1, "#text": 12}}.to_xml b
end
end
end
end
end
47 changes: 34 additions & 13 deletions src/oq.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ require "yaml"

require "./to_xml"

# A performant, and portable jq wrapper to support formats other than JSON.
# A performant and portable jq wrapper to support formats other than JSON.
module Oq
# The support formats that can be converted to/from.
enum Format
Expand All @@ -27,31 +27,52 @@ module Oq
# The root of the XML document when transcoding to XML.
property xml_root : String = "root"

# The number of spaces to use for indentation.
property indent : Int32 = 2

# :nodoc:
property tab : Bool = false

# :nodoc:
property slurp : Bool = false
property null_input : Bool = false

# Consume the input, convert the input to JSON if needed, pass the input/args to `jq`, then convert the output if needed.
def process
input = IO::Memory.new
output = IO::Memory.new
err = IO::Memory.new
error = IO::Memory.new

ARGV.replace ARGV - @args

# Shift off the filter from ARGV
@args << ARGV.shift unless ARGV.empty?

case @input_format
when .json? then input << ARGF.gets_to_end
when .yaml?
ARGV.empty? ? (input << YAML.parse(STDIN).to_json) : (ARGV.join('\n', input) { |f, io| io << YAML.parse(File.open(f)).to_json })
if !@null_input
case @input_format
when .json? then IO.copy(ARGF, input)
when .yaml?
ARGV.empty? ? (input << YAML.parse(STDIN).to_json) : (ARGV.join('\n', input) { |f, io| io << YAML.parse(File.open(f)).to_json })
else
STDERR.puts "Not Implemented"
exit(1)
end

input.rewind
else
puts "Not Implemented"
exit(1)
@args = @args | ARGV
end

run = Process.run("jq", args, input: input.rewind, output: output, error: err)
run = parallel(
Process.run("jq", args, input: input, output: output, error: error)
)

unless run[0].success?
if output.empty? && @null_input
puts "null"
exit
end

unless run.success?
puts err.to_s
STDERR.puts error.to_s
exit(1)
end

Expand All @@ -66,7 +87,7 @@ module Oq
case @output_format
when .json? then print io
when .yaml? then print JSON.parse(io).to_yaml
when .xml? then print JSON.parse(io).to_xml root: @xml_root
when .xml? then print JSON.parse(io).to_xml root: @xml_root, indent: (@tab ? "\t" : " ")*@indent
end
end
end
Expand Down
Loading

0 comments on commit e5fa156

Please sign in to comment.