From d7713a2ec1cf6374ff1667824a76581b4a9554f2 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 8 Nov 2011 16:56:22 -0300 Subject: * ext/psych/lib/psych/tree_builder.rb: dump complex numbers, rationals, etc with reference ids. * ext/psych/lib/psych/visitors/yaml_tree.rb: ditto * ext/psych/lib/psych/visitors/to_ruby.rb: loading complex numbers, rationals, etc with reference ids. * test/psych/test_object_references.rb: corresponding tests fixes #36 --- CHANGELOG.rdoc | 9 +++++ lib/psych/tree_builder.rb | 4 ++- lib/psych/visitors/to_ruby.rb | 29 +++++++++------- lib/psych/visitors/yaml_tree.rb | 14 ++++---- test/psych/test_object_references.rb | 67 ++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 test/psych/test_object_references.rb diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 06ace09..baa7a72 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -1,3 +1,12 @@ +Wed Nov 9 04:52:16 2011 Aaron Patterson + + * ext/psych/lib/psych/tree_builder.rb: dump complex numbers, + rationals, etc with reference ids. + * ext/psych/lib/psych/visitors/yaml_tree.rb: ditto + * ext/psych/lib/psych/visitors/to_ruby.rb: loading complex numbers, + rationals, etc with reference ids. + * test/psych/test_object_references.rb: corresponding tests + Mon Nov 7 20:31:52 2011 Aaron Patterson * ext/psych/lib/psych/scalar_scanner.rb: make sure strings that look diff --git a/lib/psych/tree_builder.rb b/lib/psych/tree_builder.rb index 8b4e972..c8f3447 100644 --- a/lib/psych/tree_builder.rb +++ b/lib/psych/tree_builder.rb @@ -72,7 +72,9 @@ module Psych end def scalar value, anchor, tag, plain, quoted, style - @last.children << Nodes::Scalar.new(value,anchor,tag,plain,quoted,style) + s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style) + @last.children << s + s end def alias anchor diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index 5cef198..4267f4d 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -31,9 +31,7 @@ module Psych result end - def visit_Psych_Nodes_Scalar o - @st[o.anchor] = o.value if o.anchor - + def deserialize o if klass = Psych.load_tags[o.tag] instance = klass.allocate @@ -92,6 +90,11 @@ module Psych @ss.tokenize o.value end end + private :deserialize + + def visit_Psych_Nodes_Scalar o + register o, deserialize(o) + end def visit_Psych_Nodes_Sequence o if klass = Psych.load_tags[o.tag] @@ -108,15 +111,13 @@ module Psych case o.tag when '!omap', 'tag:yaml.org,2002:omap' - map = Psych::Omap.new - @st[o.anchor] = map if o.anchor + map = register(o, Psych::Omap.new) o.children.each { |a| map[accept(a.children.first)] = accept a.children.last } map else - list = [] - @st[o.anchor] = list if o.anchor + list = register(o, []) o.children.each { |c| list.push accept c } list end @@ -135,8 +136,7 @@ module Psych klass = resolve_class($1) if klass - s = klass.allocate - @st[o.anchor] = s if o.anchor + s = register(o, klass.allocate) members = {} struct_members = s.members.map { |x| x.to_sym } @@ -158,7 +158,7 @@ module Psych when '!ruby/range' h = Hash[*o.children.map { |c| accept c }] - Range.new(h['begin'], h['end'], h['excl']) + register o, Range.new(h['begin'], h['end'], h['excl']) when /^!ruby\/exception:?(.*)?$/ h = Hash[*o.children.map { |c| accept c }] @@ -177,11 +177,11 @@ module Psych when '!ruby/object:Complex' h = Hash[*o.children.map { |c| accept c }] - Complex(h['real'], h['image']) + register o, Complex(h['real'], h['image']) when '!ruby/object:Rational' h = Hash[*o.children.map { |c| accept c }] - Rational(h['numerator'], h['denominator']) + register o, Rational(h['numerator'], h['denominator']) when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' @@ -209,6 +209,11 @@ module Psych end private + def register node, object + @st[node.anchor] = object if node.anchor + object + end + def revive_hash hash, o @st[o.anchor] = hash if o.anchor diff --git a/lib/psych/visitors/yaml_tree.rb b/lib/psych/visitors/yaml_tree.rb index 5a09285..523ad77 100644 --- a/lib/psych/visitors/yaml_tree.rb +++ b/lib/psych/visitors/yaml_tree.rb @@ -159,13 +159,13 @@ module Psych end def visit_Regexp o - @emitter.scalar o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY + register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY) end def visit_DateTime o formatted = format_time o.to_time tag = '!ruby/object:DateTime' - @emitter.scalar formatted, nil, tag, false, false, Nodes::Scalar::ANY + register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY) end def visit_Time o @@ -174,7 +174,7 @@ module Psych end def visit_Rational o - @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK) + register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK) [ 'denominator', o.denominator.to_s, @@ -187,7 +187,7 @@ module Psych end def visit_Complex o - @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK) + register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK) ['real', o.real.to_s, 'image', o.imag.to_s].each do |m| @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY @@ -255,16 +255,16 @@ module Psych def visit_Module o raise TypeError, "can't dump anonymous module: #{o}" unless o.name - @emitter.scalar o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED + register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Class o raise TypeError, "can't dump anonymous class: #{o}" unless o.name - @emitter.scalar o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED + register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED) end def visit_Range o - @emitter.start_mapping nil, '!ruby/range', false, Nodes::Mapping::BLOCK + register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK) ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m| accept m end diff --git a/test/psych/test_object_references.rb b/test/psych/test_object_references.rb new file mode 100644 index 0000000..77cc96e --- /dev/null +++ b/test/psych/test_object_references.rb @@ -0,0 +1,67 @@ +require 'psych/helper' + +module Psych + class TestObjectReferences < TestCase + def test_range_has_references + assert_reference_trip 1..2 + end + + def test_module_has_references + assert_reference_trip Psych + end + + def test_class_has_references + assert_reference_trip TestObjectReferences + end + + def test_rational_has_references + assert_reference_trip Rational('1.2') + end + + def test_complex_has_references + assert_reference_trip Complex(1, 2) + end + + def test_datetime_has_references + assert_reference_trip DateTime.now + end + + def assert_reference_trip obj + yml = Psych.dump([obj, obj]) + assert_match(/\*\d+/, yml) + data = Psych.load yml + assert_equal data.first.object_id, data.last.object_id + end + + def test_float_references + data = Psych.load <<-eoyml +--- +- &name 1.2 +- *name + eoyml + assert_equal data.first, data.last + assert_equal data.first.object_id, data.last.object_id + end + + def test_binary_references + data = Psych.load <<-eoyml +--- +- &name !binary |- + aGVsbG8gd29ybGQh +- *name + eoyml + assert_equal data.first, data.last + assert_equal data.first.object_id, data.last.object_id + end + + def test_regexp_references + data = Psych.load <<-eoyml +--- +- &name !ruby/regexp /pattern/i +- *name + eoyml + assert_equal data.first, data.last + assert_equal data.first.object_id, data.last.object_id + end + end +end -- cgit v1.2.3