diff options
-rw-r--r-- | lib/puppet/application/face_base.rb | 63 | ||||
-rw-r--r-- | lib/puppet/face/catalog/select.rb | 2 | ||||
-rw-r--r-- | lib/puppet/face/plugin.rb | 2 | ||||
-rw-r--r-- | lib/puppet/interface/action_builder.rb | 2 | ||||
-rw-r--r-- | lib/puppet/network/formats.rb | 36 | ||||
-rwxr-xr-x | spec/unit/application/face_base_spec.rb | 24 | ||||
-rwxr-xr-x | spec/unit/interface/action_builder_spec.rb | 2 | ||||
-rwxr-xr-x | spec/unit/network/formats_spec.rb | 62 |
8 files changed, 141 insertions, 52 deletions
diff --git a/lib/puppet/application/face_base.rb b/lib/puppet/application/face_base.rb index 31e58aca4..8c1e03e3f 100644 --- a/lib/puppet/application/face_base.rb +++ b/lib/puppet/application/face_base.rb @@ -29,56 +29,31 @@ class Puppet::Application::FaceBase < Puppet::Application attr_accessor :face, :action, :type, :arguments, :render_as def render_as=(format) - if format == :for_humans or format == :json - @render_as = format - elsif network_format = Puppet::Network::FormatHandler.format(format) - method = network_format.render_method - if method == "to_pson" then - @render_as = :json - else - @render_as = method.to_sym - end - else - raise ArgumentError, "I don't know how to render '#{format}'" - end + @render_as = case format.to_sym + when :for_humans then + # We have an old alias name for :console, which went out in + # 2.7.0rc1, so we are going to carry it forward for a + # while. --daniel 2011-05-04 + Puppet::Network::FormatHandler.format(:console) + when :json then + Puppet::Network::FormatHandler.format(:pson) + else + Puppet::Network::FormatHandler.format(format) + end + @render_as or raise ArgumentError, "I don't know how to render '#{format}'" end def render(result) # Invoke the rendering hook supplied by the user, if appropriate. - if hook = action.when_rendering(render_as) then + if hook = action.when_rendering(render_as.name) + result = hook.call(result) + elsif render_as.name == :console and hook = action.when_rendering(:for_humans) + # We have an old alias name for :console, which went out in 2.7.0rc1, so + # we are going to carry it forward for a while. --daniel 2011-05-04 result = hook.call(result) end - if render_as == :for_humans then - render_for_humans(result) - elsif render_as == :json - PSON::pretty_generate(result, :allow_nan => true, :max_nesting => false) - else - result.send(render_as) - end - end - - def render_for_humans(result) - # String to String - return result if result.is_a? String - return result if result.is_a? Numeric - - # Simple hash to table - if result.is_a? Hash and result.keys.all? { |x| x.is_a? String or x.is_a? Numeric } - output = '' - column_a = result.map do |k,v| k.to_s.length end.max + 2 - column_b = 79 - column_a - result.sort_by { |k,v| k.to_s } .each do |key, value| - output << key.to_s.ljust(column_a) - output << PP.pp(value, '', column_b). - chomp.gsub(/\n */) { |x| x + (' ' * column_a) } - output << "\n" - end - return output - end - - # ...or pretty-print the inspect outcome. - return result.pretty_inspect + render_as.render(result) end def preinit @@ -204,7 +179,7 @@ class Puppet::Application::FaceBase < Puppet::Application @arguments << options # If we don't have a rendering format, set one early. - self.render_as ||= (@action.render_as || :for_humans) + self.render_as ||= (@action.render_as || :console) end diff --git a/lib/puppet/face/catalog/select.rb b/lib/puppet/face/catalog/select.rb index a8ecd82fa..a68a8e0f3 100644 --- a/lib/puppet/face/catalog/select.rb +++ b/lib/puppet/face/catalog/select.rb @@ -15,7 +15,7 @@ Puppet::Face.define(:catalog, '0.0.1') do end end - when_rendering :for_humans do |value| + when_rendering :console do |value| if value.nil? then "no matching resources found" else diff --git a/lib/puppet/face/plugin.rb b/lib/puppet/face/plugin.rb index 4b45ed3a1..8a2559405 100644 --- a/lib/puppet/face/plugin.rb +++ b/lib/puppet/face/plugin.rb @@ -20,7 +20,7 @@ Puppet::Face.define(:plugin, '0.0.1') do Puppet[:pluginsignore]).evaluate end - when_rendering :for_humans do |value| + when_rendering :console do |value| if value.empty? then "No plugins downloaded." else diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb index 0bf4f1408..16305530a 100644 --- a/lib/puppet/interface/action_builder.rb +++ b/lib/puppet/interface/action_builder.rb @@ -38,6 +38,8 @@ class Puppet::Interface::ActionBuilder def render_as(value = nil) value.nil? and raise ArgumentError, "You must give a rendering format to render_as" + # :for_humans is a compatibility alias for :console, but since we shipped + # it in 2.7.0rc1 we need to support it ongoing. --daniel 2011-05-04 formats = Puppet::Network::FormatHandler.formats << :for_humans unless formats.include? value raise ArgumentError, "#{value.inspect} is not a valid rendering format: #{formats.sort.join(", ")}" diff --git a/lib/puppet/network/formats.rb b/lib/puppet/network/formats.rb index 4ca3240d4..082c83ee3 100644 --- a/lib/puppet/network/formats.rb +++ b/lib/puppet/network/formats.rb @@ -160,3 +160,39 @@ end # This is really only ever going to be used for Catalogs. Puppet::Network::FormatHandler.create_serialized_formats(:dot, :required_methods => [:render_method]) + + +Puppet::Network::FormatHandler.create(:console, + :mime => 'text/x-console-text', + :weight => 0) do + def json + @json ||= Puppet::Network::FormatHandler.format(:pson) + end + + def render(datum) + # String to String + return datum if datum.is_a? String + return datum if datum.is_a? Numeric + + # Simple hash to table + if datum.is_a? Hash and datum.keys.all? { |x| x.is_a? String or x.is_a? Numeric } + output = '' + column_a = datum.map do |k,v| k.to_s.length end.max + 2 + column_b = 79 - column_a + datum.sort_by { |k,v| k.to_s } .each do |key, value| + output << key.to_s.ljust(column_a) + output << json.render(value). + chomp.gsub(/\n */) { |x| x + (' ' * column_a) } + output << "\n" + end + return output + end + + # ...or pretty-print the inspect outcome. + return json.render(datum) + end + + def render_multiple(data) + data.collect(&:render).join("\n") + end +end diff --git a/spec/unit/application/face_base_spec.rb b/spec/unit/application/face_base_spec.rb index 133e6b2e9..25797ea3e 100755 --- a/spec/unit/application/face_base_spec.rb +++ b/spec/unit/application/face_base_spec.rb @@ -246,14 +246,14 @@ describe Puppet::Application::FaceBase do end [[1, 2], ["one"], [{ 1 => 1 }]].each do |input| - it "should render #{input.class} using the 'pp' library" do - app.render(input).should == input.pretty_inspect + it "should render #{input.class} using JSON" do + app.render(input).should == input.to_pson.chomp end end - it "should render a non-trivially-keyed Hash with the 'pp' library" do + it "should render a non-trivially-keyed Hash with using JSON" do hash = { [1,2] => 3, [2,3] => 5, [3,4] => 7 } - app.render(hash).should == hash.pretty_inspect + app.render(hash).should == hash.to_pson.chomp end it "should render a {String,Numeric}-keyed Hash into a table" do @@ -266,7 +266,7 @@ describe Puppet::Application::FaceBase do app.render(hash).should == <<EOT 5 5 6.0 6 -four #{object.pretty_inspect.chomp} +four #{object.to_pson.chomp} one 1 three {} two [] @@ -274,6 +274,7 @@ EOT end it "should render a hash nicely with a multi-line value" do + pending "Moving to PSON rather than PP makes this unsupportable." hash = { "number" => { "1" => '1' * 40, "2" => '2' * 40, '3' => '3' * 40 }, "text" => { "a" => 'a' * 40, 'b' => 'b' * 40, 'c' => 'c' * 40 } @@ -289,7 +290,7 @@ EOT end it "should invoke the action rendering hook while rendering" do - app.action.set_rendering_method_for(:for_humans, proc { |value| "bi-winning!" }) + app.action.set_rendering_method_for(:console, proc { |value| "bi-winning!" }) app.render("bi-polar?").should == "bi-winning!" end @@ -328,4 +329,15 @@ EOT }.to have_printed(/you invoked the 's' rendering hook/) end end + + describe "#render_as=" do + # This is for compatibility with the format name in 2.7.0rc1, but isn't a + # long term desirable name. We can't just randomly drop it since it was + # released, though, so it will live for a couple of major versions. + # --daniel 2011-05-04 + it "should treat :for_humans as a synonym for :console" do + app.render_as = :for_humans + app.render_as.name.should == :console + end + end end diff --git a/spec/unit/interface/action_builder_spec.rb b/spec/unit/interface/action_builder_spec.rb index e0d0ebe72..89aef26d0 100755 --- a/spec/unit/interface/action_builder_spec.rb +++ b/spec/unit/interface/action_builder_spec.rb @@ -200,6 +200,8 @@ describe Puppet::Interface::ActionBuilder do end end + # :for_humans is an alias for :console, and deprecated, but since we + # shipped it in 2.7.0rc1 we need to support it. --daniel 2011-05-04 it "should accept :for_humans format" do action = Puppet::Interface::ActionBuilder.build(face, :foo) do when_invoked do true end diff --git a/spec/unit/network/formats_spec.rb b/spec/unit/network/formats_spec.rb index 72d355192..62c2dbb9d 100755 --- a/spec/unit/network/formats_spec.rb +++ b/spec/unit/network/formats_spec.rb @@ -330,4 +330,66 @@ describe "Puppet Network Format" do end end end + + describe ":console format" do + subject { Puppet::Network::FormatHandler.format(:console) } + it { should be_an_instance_of Puppet::Network::Format } + let :json do Puppet::Network::FormatHandler.format(:pson) end + + [:intern, :intern_multiple].each do |method| + it "should not implement #{method}" do + expect { subject.send(method, String, 'blah') }.to raise_error NotImplementedError + end + end + + ["hello", 1, 1.0].each do |input| + it "should just return a #{input.inspect}" do + subject.render(input).should == input + end + end + + [[1, 2], ["one"], [{ 1 => 1 }]].each do |input| + it "should render #{input.inspect} as JSON" do + subject.render(input).should == json.render(input).chomp + end + end + + it "should render a non-trivially-keyed Hash as JSON" do + hash = { [1,2] => 3, [2,3] => 5, [3,4] => 7 } + subject.render(hash).should == json.render(hash).chomp + end + + it "should render a {String,Numeric}-keyed Hash into a table" do + object = Object.new + hash = { "one" => 1, "two" => [], "three" => {}, "four" => object, + 5 => 5, 6.0 => 6 } + + # Gotta love ASCII-betical sort order. Hope your objects are better + # structured for display than my test one is. --daniel 2011-04-18 + subject.render(hash).should == <<EOT +5 5 +6.0 6 +four #{json.render(object).chomp} +one 1 +three {} +two [] +EOT + end + + it "should render a hash nicely with a multi-line value" do + pending "Moving to PSON rather than PP makes this unsupportable." + hash = { + "number" => { "1" => '1' * 40, "2" => '2' * 40, '3' => '3' * 40 }, + "text" => { "a" => 'a' * 40, 'b' => 'b' * 40, 'c' => 'c' * 40 } + } + subject.render(hash).should == <<EOT +number {"1"=>"1111111111111111111111111111111111111111", + "2"=>"2222222222222222222222222222222222222222", + "3"=>"3333333333333333333333333333333333333333"} +text {"a"=>"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "b"=>"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "c"=>"cccccccccccccccccccccccccccccccccccccccc"} +EOT + end + end end |