summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-04-25 20:55:22 +0100
committerJames Turnbull <james@lovedthanlost.net>2009-06-06 19:53:34 +1000
commitd40068f7e70d1dc09334cac34d1bc48579b5a717 (patch)
tree07931d17146315b7c58e0b5cac494eee156d9d00
parent024ccf5b9a30977e9eee4ecf1d91eaf64f44a509 (diff)
downloadpuppet-d40068f7e70d1dc09334cac34d1bc48579b5a717.tar.gz
puppet-d40068f7e70d1dc09334cac34d1bc48579b5a717.tar.xz
puppet-d40068f7e70d1dc09334cac34d1bc48579b5a717.zip
Allowing formats to specify the methods they require
Signed-off-by: Luke Kanies <luke@madstop.com>
-rw-r--r--lib/puppet/network/format.rb67
-rwxr-xr-xspec/unit/network/format.rb31
2 files changed, 81 insertions, 17 deletions
diff --git a/lib/puppet/network/format.rb b/lib/puppet/network/format.rb
index db9458ee3..d50141ea9 100644
--- a/lib/puppet/network/format.rb
+++ b/lib/puppet/network/format.rb
@@ -6,11 +6,14 @@ require 'puppet/provider/confiner'
class Puppet::Network::Format
include Puppet::Provider::Confiner
- attr_reader :name, :mime, :weight
+ attr_reader :name, :mime, :weight, :required_methods
def initialize(name, options = {}, &block)
@name = name.to_s.downcase.intern
+ # This must be done early the values can be used to set required_methods
+ define_method_names()
+
if mime = options[:mime]
self.mime = mime
options.delete(:mime)
@@ -25,26 +28,28 @@ class Puppet::Network::Format
@weight = 5
end
+ if methods = options[:required_methods]
+ @required_methods = methods
+ options.delete(:required_methods)
+ else
+ @required_methods = [:intern_method, :intern_multiple_method, :render_multiple_method, :render_method]
+ end
+
unless options.empty?
raise ArgumentError, "Unsupported option(s) %s" % options.keys
end
instance_eval(&block) if block_given?
-
- @intern_method = "from_%s" % name
- @render_method = "to_%s" % name
- @intern_multiple_method = "from_multiple_%s" % name
- @render_multiple_method = "to_multiple_%s" % name
end
def intern(klass, text)
return klass.send(intern_method, text) if klass.respond_to?(intern_method)
- raise NotImplementedError, "%s can not intern instances from %s" % [klass, mime]
+ raise NotImplementedError, "%s does not respond to %s; can not intern instances from %s" % [klass, intern_method, mime]
end
def intern_multiple(klass, text)
return klass.send(intern_multiple_method, text) if klass.respond_to?(intern_multiple_method)
- raise NotImplementedError, "%s can not intern multiple instances from %s" % [klass, mime]
+ raise NotImplementedError, "%s does not respond to %s; can not intern multiple instances from %s" % [klass, intern_multiple_method, mime]
end
def mime=(mime)
@@ -53,21 +58,27 @@ class Puppet::Network::Format
def render(instance)
return instance.send(render_method) if instance.respond_to?(render_method)
- raise NotImplementedError, "%s can not render instances to %s" % [instance.class, mime]
+ raise NotImplementedError, "%s does not respond to %s; can not render instances to %s" % [instance.class, render_method, mime]
end
def render_multiple(instances)
# This method implicitly assumes that all instances are of the same type.
return instances[0].class.send(render_multiple_method, instances) if instances[0].class.respond_to?(render_multiple_method)
- raise NotImplementedError, "%s can not intern multiple instances to %s" % [instances[0].class, mime]
+ raise NotImplementedError, "%s does not respond to %s; can not intern multiple instances to %s" % [instances[0].class, render_multiple_method, mime]
+ end
+
+ def required_methods_present?(klass)
+ [:intern_method, :intern_multiple_method, :render_multiple_method].each do |name|
+ return false unless required_method_present?(name, klass, :class)
+ end
+
+ return false unless required_method_present?(:render_method, klass, :instance)
+
+ return true
end
def supported?(klass)
- suitable? and
- klass.respond_to?(intern_method) and
- klass.respond_to?(intern_multiple_method) and
- klass.respond_to?(render_multiple_method) and
- klass.instance_methods.include?(render_method)
+ suitable? and required_methods_present?(klass)
end
def to_s
@@ -77,4 +88,30 @@ class Puppet::Network::Format
private
attr_reader :intern_method, :render_method, :intern_multiple_method, :render_multiple_method
+
+ def define_method_names
+ @intern_method = "from_%s" % name
+ @render_method = "to_%s" % name
+ @intern_multiple_method = "from_multiple_%s" % name
+ @render_multiple_method = "to_multiple_%s" % name
+ end
+
+ def required_method_present?(name, klass, type)
+ return true unless required_methods.include?(name)
+
+ method = send(name)
+
+ if type == :class
+ has_method = klass.respond_to?(method)
+ message = "class does not respond to %s" % method
+ else
+ has_method = klass.instance_methods.include?(method)
+ message = "class instances do not respond to %s" % method
+ end
+
+ return true if has_method
+
+ Puppet.debug "Format %s not supported for %s; %s" % [name, klass, message]
+ return false
+ end
end
diff --git a/spec/unit/network/format.rb b/spec/unit/network/format.rb
index 244bff306..3e5045345 100755
--- a/spec/unit/network/format.rb
+++ b/spec/unit/network/format.rb
@@ -70,8 +70,35 @@ describe Puppet::Network::Format do
@format.should be_supported(FormatRenderer)
end
- it "should not consider a class to be supported unless it has the individual and multiple methods for rendering and interning" do
- Puppet::Network::Format.new(:yaml).should_not be_supported(String)
+ it "should default to its required methods being the individual and multiple methods for rendering and interning" do
+ Puppet::Network::Format.new(:foo).required_methods.should == [:intern_method, :intern_multiple_method, :render_multiple_method, :render_method]
+ end
+
+ it "should consider a class supported if the provided class has all required methods present" do
+ format = Puppet::Network::Format.new(:foo)
+ [:intern_method, :intern_multiple_method, :render_multiple_method, :render_method].each do |method|
+ format.expects(:required_method_present?).with { |name, klass, type| name == method and klass == String }.returns true
+ end
+
+ format.should be_required_methods_present(String)
+ end
+
+ it "should consider a class not supported if any required methods are missing from the provided class" do
+ format = Puppet::Network::Format.new(:foo)
+ format.stubs(:required_method_present?).returns true
+ format.expects(:required_method_present?).with { |name, *args| name == :intern_method }.returns false
+ format.should_not be_required_methods_present(String)
+ end
+
+ it "should be able to specify the methods required for support" do
+ Puppet::Network::Format.new(:foo, :required_methods => [:render_method, :intern_method]).required_methods.should == [:render_method, :intern_method]
+ end
+
+ it "should only test for required methods if specific methods are specified as required" do
+ format = Puppet::Network::Format.new(:foo, :required_methods => [:intern_method])
+ format.expects(:required_method_present?).with { |name, klass, type| name == :intern_method }
+
+ format.required_methods_present?(String)
end
it "should not consider a class supported unless the format is suitable" do