diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2014-12-01 13:22:26 -0800 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2014-12-01 13:22:26 -0800 |
commit | 002cc29fcb92b72a02a0ca03b0873ca4d2ace67b (patch) | |
tree | b31a5f26799736306385d03edd6cdd390541908c | |
parent | fc31992c397e936e6e5c2f45ec8984a7bc035b47 (diff) | |
parent | dbbd9e189d39de48432b89260236250ad10d2a14 (diff) | |
download | psych-002cc29fcb92b72a02a0ca03b0873ca4d2ace67b.tar.gz |
Merge branch 'master' of github.com:tenderlove/psych
* 'master' of github.com:tenderlove/psych:
backport r48512 from ruby/ruby trunk.
Add changelog for 2a4d9568f7d5d19c00231cf48eb855cc45ec3394
backport r48214 from ruby/ruby trunk.
Allow dumping any BasicObject that defines #marshal_dump or #marshal_load
-rw-r--r-- | CHANGELOG.rdoc | 7 | ||||
-rw-r--r-- | lib/psych/visitors/to_ruby.rb | 15 | ||||
-rw-r--r-- | lib/psych/visitors/yaml_tree.rb | 14 | ||||
-rw-r--r-- | test/psych/json/test_stream.rb | 2 | ||||
-rw-r--r-- | test/psych/test_emitter.rb | 3 | ||||
-rw-r--r-- | test/psych/test_json_tree.rb | 2 | ||||
-rw-r--r-- | test/psych/test_marshalable.rb | 54 |
7 files changed, 93 insertions, 4 deletions
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 5df3bcb..c6f13c2 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,10 @@ +Sun Nov 23 13:11:24 2014 Sean Griffin <sean@thoughtbot.com> + + * lib/psych/visitors/to_ruby.rb: Allow loading any BasicObject that + defines #marshal_load, fixes #100 + * lib/psych/visitors/yaml_tree.rb: Allow dumping any BasicObject that + defines #marshal_dump + Sat Aug 30 06:39:48 2014 Aaron Patterson <aaron@tenderlovemaking.com> * ext/psych/lib/psych/visitors/yaml_tree.rb: fix NameError dumping and diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index e74d5d4..e696ebd 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -271,6 +271,21 @@ module Psych end map + when /^!ruby\/marshalable:(.*)$/ + name = $1 + klass = resolve_class(name) + obj = register(o, klass.allocate) + + if obj.respond_to?(:init_with) + init_with(obj, revive_hash({}, o), o) + elsif obj.respond_to?(:marshal_load) + marshal_data = o.children.map(&method(:accept)) + obj.marshal_load(marshal_data) + obj + else + raise ArgumentError, "Cannot deserialize #{name}" + end + else revive_hash(register(o, {}), o) end diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb index 3f2427b..989e1f0 100644 --- a/lib/psych/visitors/yaml_tree.rb +++ b/lib/psych/visitors/yaml_tree.rb @@ -27,6 +27,8 @@ module Psych def key? target @obj_to_node.key? target.object_id + rescue NoMethodError + false end def id_for target @@ -411,6 +413,18 @@ module Psych end end + def visit_BasicObject o + tag = Psych.dump_tags[o.class] + tag ||= "!ruby/marshalable:#{o.class.name}" + + map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) + register(o, map) + + o.marshal_dump.each(&method(:accept)) + + @emitter.end_mapping + end + private # FIXME: Remove the index and count checks in Psych 3.0 NULL = "\x00" diff --git a/test/psych/json/test_stream.rb b/test/psych/json/test_stream.rb index 4690ad2..b0c33e6 100644 --- a/test/psych/json/test_stream.rb +++ b/test/psych/json/test_stream.rb @@ -65,7 +65,7 @@ module Psych @stream.push list json = @io.string - assert_match(/]$/, json) + assert_match(/\]$/, json) assert_match(/^--- \[/, json) assert_match(/["]one["]/, json) assert_match(/["]two["]/, json) diff --git a/test/psych/test_emitter.rb b/test/psych/test_emitter.rb index 0554ae5..1c96c12 100644 --- a/test/psych/test_emitter.rb +++ b/test/psych/test_emitter.rb @@ -11,8 +11,7 @@ module Psych end def test_line_width - assert_equal 0, @emitter.line_width - assert_equal 10, @emitter.line_width = 10 + @emitter.line_width = 10 assert_equal 10, @emitter.line_width end diff --git a/test/psych/test_json_tree.rb b/test/psych/test_json_tree.rb index 60f8321..a23fc1a 100644 --- a/test/psych/test_json_tree.rb +++ b/test/psych/test_json_tree.rb @@ -45,7 +45,7 @@ module Psych def test_list_to_json list = %w{ one two } json = Psych.to_json(list) - assert_match(/]$/, json) + assert_match(/\]$/, json) assert_match(/^\[/, json) assert_match(/"one"/, json) assert_match(/"two"/, json) diff --git a/test/psych/test_marshalable.rb b/test/psych/test_marshalable.rb new file mode 100644 index 0000000..7df74ee --- /dev/null +++ b/test/psych/test_marshalable.rb @@ -0,0 +1,54 @@ +require_relative 'helper' +require 'delegate' + +module Psych + class TestMarshalable < TestCase + def test_objects_defining_marshal_dump_and_marshal_load_can_be_dumped + sd = SimpleDelegator.new(1) + loaded = Psych.load(Psych.dump(sd)) + + assert_instance_of(SimpleDelegator, loaded) + assert_equal(sd, loaded) + end + + class PsychCustomMarshalable < BasicObject + attr_reader :foo + + def initialize(foo) + @foo = foo + end + + def marshal_dump + [foo] + end + + def mashal_load(data) + @foo = data[0] + end + + def init_with(coder) + @foo = coder['foo'] + end + + def encode_with(coder) + coder['foo'] = 2 + end + + def respond_to?(method) + [:marshal_dump, :marshal_load, :init_with, :encode_with].include?(method) + end + + def class + PsychCustomMarshalable + end + end + + def test_init_with_takes_priority_over_marshal_methods + obj = PsychCustomMarshalable.new(1) + loaded = Psych.load(Psych.dump(obj)) + + assert(PsychCustomMarshalable === loaded) + assert_equal(2, loaded.foo) + end + end +end |