diff options
-rw-r--r-- | Rakefile | 2 | ||||
-rw-r--r-- | ext/psych/parser.c | 1 | ||||
-rw-r--r-- | lib/psych.rb | 1 | ||||
-rw-r--r-- | lib/psych/deprecated.rb | 18 | ||||
-rw-r--r-- | lib/psych/visitors/to_ruby.rb | 10 | ||||
-rw-r--r-- | lib/psych/visitors/yaml_tree.rb | 13 | ||||
-rw-r--r-- | test/psych/test_deprecated.rb | 135 |
7 files changed, 177 insertions, 3 deletions
@@ -26,7 +26,7 @@ Hoe.spec 'psych' do end end -Hoe.add_include_dirs('.') +Hoe.add_include_dirs('.:lib/psych') task :test => :compile diff --git a/ext/psych/parser.c b/ext/psych/parser.c index dd64c25..5f5b253 100644 --- a/ext/psych/parser.c +++ b/ext/psych/parser.c @@ -57,6 +57,7 @@ static VALUE parse(VALUE self, VALUE yaml) if(rb_respond_to(yaml, id_read)) { yaml_parser_set_input(&parser, io_reader, (void *)yaml); } else { + Check_Type(yaml, T_STRING); yaml_parser_set_input_string( &parser, (const unsigned char *)StringValuePtr(yaml), diff --git a/lib/psych.rb b/lib/psych.rb index 9b4b215..42cd887 100644 --- a/lib/psych.rb +++ b/lib/psych.rb @@ -8,6 +8,7 @@ require 'psych/omap' require 'psych/set' require 'psych/coder' require 'psych/core_ext' +require 'psych/deprecated' ### # = Overview diff --git a/lib/psych/deprecated.rb b/lib/psych/deprecated.rb new file mode 100644 index 0000000..ec3cfe4 --- /dev/null +++ b/lib/psych/deprecated.rb @@ -0,0 +1,18 @@ +module Psych + module DeprecatedMethods # :nodoc: + attr_accessor :taguri + attr_accessor :to_yaml_style + end + + def self.quick_emit thing, opts = {}, &block # :nodoc: + target = eval 'self', block.binding + target.extend DeprecatedMethods + metaclass = class << target; self; end + metaclass.send(:define_method, :encode_with) do |coder| + target.taguri = coder.tag + target.to_yaml_style = coder.style + block.call coder + end + target.psych_to_yaml unless opts[:nodump] + end +end diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index 2790cde..56c9700 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -219,10 +219,16 @@ module Psych end def init_with o, h, node + c = Psych::Coder.new(node.tag) + c.map = h + if o.respond_to?(:init_with) - c = Psych::Coder.new(node.tag) - c.map = h o.init_with c + elsif o.respond_to?(:yaml_initialize) + if $VERBOSE + "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\"" + end + o.yaml_initialize c.tag, c.map else h.each { |k,v| o.instance_variable_set(:"@#{k}", v) } end diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb index e1e89a0..3cbb695 100644 --- a/lib/psych/visitors/yaml_tree.rb +++ b/lib/psych/visitors/yaml_tree.rb @@ -36,6 +36,19 @@ module Psych return append Nodes::Alias.new target.object_id.to_s end + if target.respond_to?(:to_yaml) + loc = target.method(:to_yaml).source_location.first + if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/ + unless target.respond_to?(:encode_with) + if $VERBOSE + warn "implementing to_yaml is deprecated, please implement \"encode_with\"" + end + + target.to_yaml(:nodump => true) + end + end + end + if target.respond_to?(:encode_with) dump_coder target else diff --git a/test/psych/test_deprecated.rb b/test/psych/test_deprecated.rb new file mode 100644 index 0000000..7e36daa --- /dev/null +++ b/test/psych/test_deprecated.rb @@ -0,0 +1,135 @@ +require_relative 'helper' + +module Psych + class TestDeprecated < TestCase + class QuickEmitter + attr_reader :name + attr_reader :value + + def initialize + @name = 'hello!!' + @value = 'Friday!' + end + + def to_yaml opts = {} + Psych.quick_emit object_id, opts do |out| + out.map taguri, to_yaml_style do |map| + map.add 'name', @name + map.add 'value', nil + end + end + end + end + + def setup + @qe = QuickEmitter.new + end + + def test_quick_emit + qe2 = Psych.load @qe.to_yaml + assert_equal @qe.name, qe2.name + assert_instance_of QuickEmitter, qe2 + assert_nil qe2.value + end + + def test_recursive_quick_emit + hash = { :qe => @qe } + hash2 = Psych.load Psych.dump hash + qe = hash2[:qe] + + assert_equal @qe.name, qe.name + assert_instance_of QuickEmitter, qe + assert_nil qe.value + end + + class QuickEmitterEncodeWith + attr_reader :name + attr_reader :value + + def initialize + @name = 'hello!!' + @value = 'Friday!' + end + + def encode_with coder + coder.map do |map| + map.add 'name', @name + map.add 'value', nil + end + end + + def to_yaml opts = {} + raise + end + end + + ### + # An object that defines both to_yaml and encode_with should only call + # encode_with. + def test_recursive_quick_emit_encode_with + qeew = QuickEmitterEncodeWith.new + hash = { :qe => qeew } + hash2 = Psych.load Psych.dump hash + qe = hash2[:qe] + + assert_equal qeew.name, qe.name + assert_instance_of QuickEmitterEncodeWith, qe + assert_nil qe.value + end + + class YamlInit + attr_reader :name + attr_reader :value + + def initialize + @name = 'hello!!' + @value = 'Friday!' + end + + def yaml_initialize tag, vals + vals.each { |ivar, val| instance_variable_set "@#{ivar}", 'TGIF!' } + end + end + + def test_yaml_initialize + hash = { :yi => YamlInit.new } + hash2 = Psych.load Psych.dump hash + yi = hash2[:yi] + + assert_equal 'TGIF!', yi.name + assert_equal 'TGIF!', yi.value + assert_instance_of YamlInit, yi + end + + class YamlInitAndInitWith + attr_reader :name + attr_reader :value + + def initialize + @name = 'shaners' + @value = 'Friday!' + end + + def init_with coder + coder.map.each { |ivar, val| instance_variable_set "@#{ivar}", 'TGIF!' } + end + + def yaml_initialize tag, vals + raise + end + end + + ### + # An object that implements both yaml_initialize and init_with should not + # receive the yaml_initialize call. + def test_yaml_initialize_and_init_with + hash = { :yi => YamlInitAndInitWith.new } + hash2 = Psych.load Psych.dump hash + yi = hash2[:yi] + + assert_equal 'TGIF!', yi.name + assert_equal 'TGIF!', yi.value + assert_instance_of YamlInitAndInitWith, yi + end + end +end |