[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]