diff options
author | Jean Boussier <[email protected]> | 2025-04-30 09:13:29 +0200 |
---|---|---|
committer | git <[email protected]> | 2025-04-30 18:31:33 +0000 |
commit | f55138c9e7b6c62847eb4cefbfb452233615b59f (patch) | |
tree | d51938c5e4484e4e751209a043bc1f1e965dd0e3 | |
parent | 46c9e46ef624178dfa5abe5f76ab2142e07c3b29 (diff) |
[ruby/psych] Handle Ruby 3.5 new Set class
Since `Set` no longer is a regular object class holding a Hash
it needs to be specially handled.
https://github.com/ruby/psych/commit/c2d185d27c
-rw-r--r-- | ext/psych/lib/psych/core_ext.rb | 14 | ||||
-rw-r--r-- | test/psych/test_psych_set.rb | 57 | ||||
-rw-r--r-- | test/psych/test_set.rb | 61 |
3 files changed, 91 insertions, 41 deletions
diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb index 0721a133c3..950b20f2d6 100644 --- a/ext/psych/lib/psych/core_ext.rb +++ b/ext/psych/lib/psych/core_ext.rb @@ -17,3 +17,17 @@ end if defined?(::IRB) require_relative 'y' end + + +# TODO: how best to check for builtin Set? +if defined?(::Set) && Object.const_source_location(:Set) == ["ruby", 0] + class Set + def encode_with(coder) + coder["hash"] = to_h + end + + def init_with(coder) + replace(coder["hash"].keys) + end + end +end diff --git a/test/psych/test_psych_set.rb b/test/psych/test_psych_set.rb new file mode 100644 index 0000000000..c72cd73f18 --- /dev/null +++ b/test/psych/test_psych_set.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true +require_relative 'helper' + +module Psych + class TestPsychSet < TestCase + def setup + super + @set = Psych::Set.new + @set['foo'] = 'bar' + @set['bar'] = 'baz' + end + + def test_dump + assert_match(/!set/, Psych.dump(@set)) + end + + def test_roundtrip + assert_cycle(@set) + end + + ### + # FIXME: Syck should also support !!set as shorthand + def test_load_from_yaml + loaded = Psych.unsafe_load(<<-eoyml) +--- !set +foo: bar +bar: baz + eoyml + assert_equal(@set, loaded) + end + + def test_loaded_class + assert_instance_of(Psych::Set, Psych.unsafe_load(Psych.dump(@set))) + end + + def test_set_shorthand + loaded = Psych.unsafe_load(<<-eoyml) +--- !!set +foo: bar +bar: baz + eoyml + assert_instance_of(Psych::Set, loaded) + end + + def test_set_self_reference + @set['self'] = @set + assert_cycle(@set) + end + + def test_stringify_names + @set[:symbol] = :value + + assert_match(/^:symbol: :value/, Psych.dump(@set)) + assert_match(/^symbol: :value/, Psych.dump(@set, stringify_names: true)) + end + end +end diff --git a/test/psych/test_set.rb b/test/psych/test_set.rb index b4968d3425..ccd591c626 100644 --- a/test/psych/test_set.rb +++ b/test/psych/test_set.rb @@ -1,57 +1,36 @@ +# encoding: UTF-8 # frozen_string_literal: true require_relative 'helper' +require 'set' unless defined?(Set) module Psych class TestSet < TestCase def setup - super - @set = Psych::Set.new - @set['foo'] = 'bar' - @set['bar'] = 'baz' + @set = ::Set.new([1, 2, 3]) end def test_dump - assert_match(/!set/, Psych.dump(@set)) + assert_equal <<~YAML, Psych.dump(@set) + --- !ruby/object:Set + hash: + 1: true + 2: true + 3: true + YAML end - def test_roundtrip - assert_cycle(@set) - end - - ### - # FIXME: Syck should also support !!set as shorthand - def test_load_from_yaml - loaded = Psych.unsafe_load(<<-eoyml) ---- !set -foo: bar -bar: baz - eoyml - assert_equal(@set, loaded) + def test_load + assert_equal @set, Psych.load(<<~YAML, permitted_classes: [::Set]) + --- !ruby/object:Set + hash: + 1: true + 2: true + 3: true + YAML end - def test_loaded_class - assert_instance_of(Psych::Set, Psych.unsafe_load(Psych.dump(@set))) - end - - def test_set_shorthand - loaded = Psych.unsafe_load(<<-eoyml) ---- !!set -foo: bar -bar: baz - eoyml - assert_instance_of(Psych::Set, loaded) - end - - def test_set_self_reference - @set['self'] = @set - assert_cycle(@set) - end - - def test_stringify_names - @set[:symbol] = :value - - assert_match(/^:symbol: :value/, Psych.dump(@set)) - assert_match(/^symbol: :value/, Psych.dump(@set, stringify_names: true)) + def test_roundtrip + assert_equal @set, Psych.load(Psych.dump(@set), permitted_classes: [::Set]) end end end |