summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rakefile2
-rw-r--r--ext/psych/parser.c1
-rw-r--r--lib/psych.rb1
-rw-r--r--lib/psych/deprecated.rb18
-rw-r--r--lib/psych/visitors/to_ruby.rb10
-rw-r--r--lib/psych/visitors/yaml_tree.rb13
-rw-r--r--test/psych/test_deprecated.rb135
7 files changed, 177 insertions, 3 deletions
diff --git a/Rakefile b/Rakefile
index f23126a..342fc83 100644
--- a/Rakefile
+++ b/Rakefile
@@ -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