ruby-changes:19914
From: tenderlove <ko1@a...>
Date: Thu, 9 Jun 2011 10:58:16 +0900 (JST)
Subject: [ruby-changes:19914] tenderlove:r31961 (trunk): * ext/psych/lib/psych/visitors/to_ruby.rb: Hash subclasses can be read
tenderlove 2011-06-09 10:58:07 +0900 (Thu, 09 Jun 2011) New Revision: 31961 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31961 Log: * ext/psych/lib/psych/visitors/to_ruby.rb: Hash subclasses can be read from YAML files. * ext/psych/lib/psych/visitors/yaml_tree.rb: Hash subclasses can be dumped to YAML files. * test/psych/test_hash.rb: corresponding test. Modified files: trunk/ChangeLog trunk/ext/psych/lib/psych/visitors/to_ruby.rb trunk/ext/psych/lib/psych/visitors/yaml_tree.rb trunk/test/psych/test_hash.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 31960) +++ ChangeLog (revision 31961) @@ -1,3 +1,11 @@ +Thu Jun 9 10:57:03 2011 Aaron Patterson <aaron@t...> + + * ext/psych/lib/psych/visitors/to_ruby.rb: Hash subclasses can be read + from YAML files. + * ext/psych/lib/psych/visitors/yaml_tree.rb: Hash subclasses can be + dumped to YAML files. + * test/psych/test_hash.rb: corresponding test. + Thu Jun 9 09:18:51 2011 Aaron Patterson <aaron@t...> * ext/psych/lib/psych/visitors/to_ruby.rb: Ruby modules can be loaded Index: ext/psych/lib/psych/visitors/yaml_tree.rb =================================================================== --- ext/psych/lib/psych/visitors/yaml_tree.rb (revision 31960) +++ ext/psych/lib/psych/visitors/yaml_tree.rb (revision 31961) @@ -265,8 +265,11 @@ end def visit_Hash o - register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK)) + tag = o.class == ::Hash ? nil : "!ruby/hash:#{o.class}" + implicit = !tag + register(o, @emitter.start_mapping(nil, tag, implicit, Psych::Nodes::Mapping::BLOCK)) + o.each do |k,v| accept k accept v Index: ext/psych/lib/psych/visitors/to_ruby.rb =================================================================== --- ext/psych/lib/psych/visitors/to_ruby.rb (revision 31960) +++ ext/psych/lib/psych/visitors/to_ruby.rb (revision 31961) @@ -120,6 +120,7 @@ def visit_Psych_Nodes_Mapping o return revive(Psych.load_tags[o.tag], o) if Psych.load_tags[o.tag] + return revive_hash({}, o) unless o.tag case o.tag when '!str', 'tag:yaml.org,2002:str' @@ -183,30 +184,12 @@ obj = revive((resolve_class(name) || Object), o) @st[o.anchor] = obj if o.anchor obj - else - hash = {} - @st[o.anchor] = hash if o.anchor - o.children.each_slice(2) { |k,v| - key = accept(k) + when /^!map:(.*)$/, /^!ruby\/hash:(.*)$/ + revive_hash resolve_class($1).new, o - if key == '<<' - case v - when Nodes::Alias - hash.merge! accept(v) - when Nodes::Sequence - accept(v).reverse_each do |value| - hash.merge! value - end - else - hash[key] = accept(v) - end - else - hash[key] = accept(v) - end - - } - hash + else + revive_hash({}, o) end end @@ -223,6 +206,31 @@ end private + def revive_hash hash, o + @st[o.anchor] = hash if o.anchor + + o.children.each_slice(2) { |k,v| + key = accept(k) + + if key == '<<' + case v + when Nodes::Alias + hash.merge! accept(v) + when Nodes::Sequence + accept(v).reverse_each do |value| + hash.merge! value + end + else + hash[key] = accept(v) + end + else + hash[key] = accept(v) + end + + } + hash + end + def revive klass, node s = klass.allocate h = Hash[*node.children.map { |c| accept c }] Index: test/psych/test_hash.rb =================================================================== --- test/psych/test_hash.rb (revision 31960) +++ test/psych/test_hash.rb (revision 31961) @@ -2,11 +2,25 @@ module Psych class TestHash < TestCase + class X < Hash + end + def setup super @hash = { :a => 'b' } end + def test_empty_subclass + assert_match "!ruby/hash:#{X}", Psych.dump(X.new) + x = Psych.load Psych.dump X.new + assert_equal X, x.class + end + + def test_map + x = Psych.load "--- !map:#{X} { }\n" + assert_equal X, x.class + end + def test_self_referential @hash['self'] = @hash assert_cycle(@hash) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/