psych 3.1.0 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +24 -0
- data/{ext/psych/yaml/LICENSE → LICENSE} +9 -7
- data/README.md +22 -17
- data/ext/psych/depend +14 -0
- data/ext/psych/extconf.rb +42 -28
- data/ext/psych/psych.c +6 -4
- data/ext/psych/psych_emitter.c +155 -121
- data/ext/psych/psych_parser.c +274 -302
- data/ext/psych/psych_to_ruby.c +0 -1
- data/ext/psych/psych_yaml_tree.c +0 -13
- data/lib/psych/class_loader.rb +10 -8
- data/lib/psych/core_ext.rb +1 -1
- data/lib/psych/exception.rb +16 -2
- data/lib/psych/handler.rb +1 -1
- data/lib/psych/handlers/document_stream.rb +1 -1
- data/lib/psych/handlers/recorder.rb +1 -1
- data/lib/psych/json/stream.rb +2 -2
- data/lib/psych/json/tree_builder.rb +1 -1
- data/lib/psych/nodes/node.rb +5 -5
- data/lib/psych/nodes/scalar.rb +1 -1
- data/lib/psych/nodes.rb +7 -7
- data/lib/psych/parser.rb +13 -0
- data/lib/psych/scalar_scanner.rb +39 -47
- data/lib/psych/syntax_error.rb +1 -1
- data/lib/psych/tree_builder.rb +3 -3
- data/lib/psych/versions.rb +3 -3
- data/lib/psych/visitors/json_tree.rb +1 -1
- data/lib/psych/visitors/to_ruby.rb +60 -26
- data/lib/psych/visitors/visitor.rb +17 -3
- data/lib/psych/visitors/yaml_tree.rb +103 -71
- data/lib/psych/visitors.rb +6 -6
- data/lib/psych.rb +260 -138
- metadata +20 -53
- data/.gitignore +0 -16
- data/.travis.yml +0 -22
- data/CHANGELOG.rdoc +0 -583
- data/Gemfile +0 -3
- data/Mavenfile +0 -7
- data/Rakefile +0 -48
- data/bin/console +0 -7
- data/bin/setup +0 -6
- data/ext/psych/yaml/api.c +0 -1393
- data/ext/psych/yaml/config.h +0 -10
- data/ext/psych/yaml/dumper.c +0 -394
- data/ext/psych/yaml/emitter.c +0 -2324
- data/ext/psych/yaml/loader.c +0 -444
- data/ext/psych/yaml/parser.c +0 -1370
- data/ext/psych/yaml/reader.c +0 -469
- data/ext/psych/yaml/scanner.c +0 -3578
- data/ext/psych/yaml/writer.c +0 -141
- data/ext/psych/yaml/yaml.h +0 -1971
- data/ext/psych/yaml/yaml_private.h +0 -688
- data/psych.gemspec +0 -75
data/ext/psych/psych_to_ruby.c
CHANGED
data/ext/psych/psych_yaml_tree.c
CHANGED
@@ -2,23 +2,10 @@
|
|
2
2
|
|
3
3
|
VALUE cPsychVisitorsYamlTree;
|
4
4
|
|
5
|
-
/*
|
6
|
-
* call-seq: private_iv_get(target, prop)
|
7
|
-
*
|
8
|
-
* Get the private instance variable +prop+ from +target+
|
9
|
-
*/
|
10
|
-
static VALUE private_iv_get(VALUE self, VALUE target, VALUE prop)
|
11
|
-
{
|
12
|
-
return rb_attr_get(target, rb_intern(StringValueCStr(prop)));
|
13
|
-
}
|
14
|
-
|
15
5
|
void Init_psych_yaml_tree(void)
|
16
6
|
{
|
17
7
|
VALUE psych = rb_define_module("Psych");
|
18
8
|
VALUE visitors = rb_define_module_under(psych, "Visitors");
|
19
9
|
VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
|
20
10
|
cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
|
21
|
-
|
22
|
-
rb_define_private_method(cPsychVisitorsYamlTree, "private_iv_get", private_iv_get, 2);
|
23
11
|
}
|
24
|
-
/* vim: set noet sws=4 sw=4: */
|
data/lib/psych/class_loader.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
2
|
+
require_relative 'omap'
|
3
|
+
require_relative 'set'
|
4
4
|
|
5
5
|
module Psych
|
6
6
|
class ClassLoader # :nodoc:
|
@@ -35,9 +35,11 @@ module Psych
|
|
35
35
|
|
36
36
|
constants.each do |const|
|
37
37
|
konst = const_get const
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
39
|
+
def #{const.to_s.downcase}
|
40
|
+
load #{konst.inspect}
|
41
|
+
end
|
42
|
+
RUBY
|
41
43
|
end
|
42
44
|
|
43
45
|
private
|
@@ -69,7 +71,7 @@ module Psych
|
|
69
71
|
rescue
|
70
72
|
nil
|
71
73
|
end
|
72
|
-
}.compact]
|
74
|
+
}.compact].freeze
|
73
75
|
|
74
76
|
class Restricted < ClassLoader
|
75
77
|
def initialize classes, symbols
|
@@ -84,7 +86,7 @@ module Psych
|
|
84
86
|
if @symbols.include? sym
|
85
87
|
super
|
86
88
|
else
|
87
|
-
raise DisallowedClass, 'Symbol'
|
89
|
+
raise DisallowedClass.new('load', 'Symbol')
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
@@ -94,7 +96,7 @@ module Psych
|
|
94
96
|
if @classes.include? klassname
|
95
97
|
super
|
96
98
|
else
|
97
|
-
raise DisallowedClass, klassname
|
99
|
+
raise DisallowedClass.new('load', klassname)
|
98
100
|
end
|
99
101
|
end
|
100
102
|
end
|
data/lib/psych/core_ext.rb
CHANGED
data/lib/psych/exception.rb
CHANGED
@@ -6,9 +6,23 @@ module Psych
|
|
6
6
|
class BadAlias < Exception
|
7
7
|
end
|
8
8
|
|
9
|
+
# Subclasses `BadAlias` for backwards compatibility
|
10
|
+
class AliasesNotEnabled < BadAlias
|
11
|
+
def initialize
|
12
|
+
super "Alias parsing was not enabled. To enable it, pass `aliases: true` to `Psych::load` or `Psych::safe_load`."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Subclasses `BadAlias` for backwards compatibility
|
17
|
+
class AnchorNotDefined < BadAlias
|
18
|
+
def initialize anchor_name
|
19
|
+
super "An alias referenced an unknown anchor: #{anchor_name}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
9
23
|
class DisallowedClass < Exception
|
10
|
-
def initialize klass_name
|
11
|
-
super "Tried to
|
24
|
+
def initialize action, klass_name
|
25
|
+
super "Tried to #{action} unspecified class: #{klass_name}"
|
12
26
|
end
|
13
27
|
end
|
14
28
|
end
|
data/lib/psych/handler.rb
CHANGED
@@ -119,7 +119,7 @@ module Psych
|
|
119
119
|
# +tag+ is an associated tag or nil
|
120
120
|
# +plain+ is a boolean value
|
121
121
|
# +quoted+ is a boolean value
|
122
|
-
# +style+ is an integer
|
122
|
+
# +style+ is an integer indicating the string style
|
123
123
|
#
|
124
124
|
# See the constants in Psych::Nodes::Scalar for the possible values of
|
125
125
|
# +style+
|
data/lib/psych/json/stream.rb
CHANGED
data/lib/psych/nodes/node.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
require 'psych/scalar_scanner'
|
2
|
+
require_relative '../class_loader'
|
3
|
+
require_relative '../scalar_scanner'
|
5
4
|
|
6
5
|
module Psych
|
7
6
|
module Nodes
|
@@ -46,8 +45,8 @@ module Psych
|
|
46
45
|
# Convert this node to Ruby.
|
47
46
|
#
|
48
47
|
# See also Psych::Visitors::ToRuby
|
49
|
-
def to_ruby
|
50
|
-
Visitors::ToRuby.create.accept(self)
|
48
|
+
def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
|
49
|
+
Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
|
51
50
|
end
|
52
51
|
alias :transform :to_ruby
|
53
52
|
|
@@ -56,6 +55,7 @@ module Psych
|
|
56
55
|
#
|
57
56
|
# See also Psych::Visitors::Emitter
|
58
57
|
def yaml io = nil, options = {}
|
58
|
+
require "stringio"
|
59
59
|
real_io = io || StringIO.new(''.encode('utf-8'))
|
60
60
|
|
61
61
|
Visitors::Emitter.new(real_io, options).accept self
|
data/lib/psych/nodes/scalar.rb
CHANGED
data/lib/psych/nodes.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
require_relative 'nodes/node'
|
3
|
+
require_relative 'nodes/stream'
|
4
|
+
require_relative 'nodes/document'
|
5
|
+
require_relative 'nodes/sequence'
|
6
|
+
require_relative 'nodes/scalar'
|
7
|
+
require_relative 'nodes/mapping'
|
8
|
+
require_relative 'nodes/alias'
|
9
9
|
|
10
10
|
module Psych
|
11
11
|
###
|
data/lib/psych/parser.rb
CHANGED
@@ -48,5 +48,18 @@ module Psych
|
|
48
48
|
@handler = handler
|
49
49
|
@external_encoding = ANY
|
50
50
|
end
|
51
|
+
|
52
|
+
###
|
53
|
+
# call-seq:
|
54
|
+
# parser.parse(yaml)
|
55
|
+
#
|
56
|
+
# Parse the YAML document contained in +yaml+. Events will be called on
|
57
|
+
# the handler set on the parser instance.
|
58
|
+
#
|
59
|
+
# See Psych::Parser and Psych::Parser#handler
|
60
|
+
|
61
|
+
def parse yaml, path = yaml.respond_to?(:path) ? yaml.path : "<unknown>"
|
62
|
+
_native_parse @handler, yaml, path
|
63
|
+
end
|
51
64
|
end
|
52
65
|
end
|
data/lib/psych/scalar_scanner.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'strscan'
|
3
2
|
|
4
3
|
module Psych
|
5
4
|
###
|
@@ -9,103 +8,97 @@ module Psych
|
|
9
8
|
TIME = /^-?\d{4}-\d{1,2}-\d{1,2}(?:[Tt]|\s+)\d{1,2}:\d\d:\d\d(?:\.\d*)?(?:\s*(?:Z|[-+]\d{1,2}:?(?:\d\d)?))?$/
|
10
9
|
|
11
10
|
# Taken from http://yaml.org/type/float.html
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
11
|
+
# Base 60, [-+]inf and NaN are handled separately
|
12
|
+
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
|
13
|
+
|
14
|
+
# Taken from http://yaml.org/type/int.html and modified to ensure at least one numerical symbol exists
|
15
|
+
INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2)
|
16
|
+
|[-+]?0[_]*[0-7][0-7_]* (?# base 8)
|
17
|
+
|[-+]?(0|[1-9][0-9_]*) (?# base 10)
|
18
|
+
|[-+]?0x[_]*[0-9a-fA-F][0-9a-fA-F_]* (?# base 16))$/x
|
19
|
+
|
20
|
+
# Same as above, but allows commas.
|
21
|
+
# Not to YML spec, but kept for backwards compatibility
|
22
|
+
INTEGER_LEGACY = /^(?:[-+]?0b[_,]*[0-1][0-1_,]* (?# base 2)
|
23
|
+
|[-+]?0[_,]*[0-7][0-7_,]* (?# base 8)
|
24
|
+
|[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
|
25
|
+
|[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x
|
21
26
|
|
22
27
|
attr_reader :class_loader
|
23
28
|
|
24
29
|
# Create a new scanner
|
25
|
-
def initialize class_loader
|
26
|
-
@string_cache = {}
|
30
|
+
def initialize class_loader, strict_integer: false
|
27
31
|
@symbol_cache = {}
|
28
32
|
@class_loader = class_loader
|
33
|
+
@strict_integer = strict_integer
|
29
34
|
end
|
30
35
|
|
31
36
|
# Tokenize +string+ returning the Ruby object
|
32
37
|
def tokenize string
|
33
38
|
return nil if string.empty?
|
34
|
-
return string if @string_cache.key?(string)
|
35
39
|
return @symbol_cache[string] if @symbol_cache.key?(string)
|
36
|
-
|
37
|
-
case string
|
40
|
+
integer_regex = @strict_integer ? INTEGER_STRICT : INTEGER_LEGACY
|
38
41
|
# Check for a String type, being careful not to get caught by hash keys, hex values, and
|
39
42
|
# special floats (e.g., -.inf).
|
40
|
-
|
41
|
-
if string.length > 5
|
42
|
-
@string_cache[string] = true
|
43
|
-
return string
|
44
|
-
end
|
43
|
+
if string.match?(%r{^[^\d.:-]?[[:alpha:]_\s!@#$%\^&*(){}<>|/\\~;=]+}) || string.match?(/\n/)
|
44
|
+
return string if string.length > 5
|
45
45
|
|
46
|
-
|
47
|
-
when /^[^ytonf~]/i
|
48
|
-
@string_cache[string] = true
|
46
|
+
if string.match?(/^[^ytonf~]/i)
|
49
47
|
string
|
50
|
-
|
48
|
+
elsif string == '~' || string.match?(/^null$/i)
|
51
49
|
nil
|
52
|
-
|
50
|
+
elsif string.match?(/^(yes|true|on)$/i)
|
53
51
|
true
|
54
|
-
|
52
|
+
elsif string.match?(/^(no|false|off)$/i)
|
55
53
|
false
|
56
54
|
else
|
57
|
-
@string_cache[string] = true
|
58
55
|
string
|
59
56
|
end
|
60
|
-
|
57
|
+
elsif string.match?(TIME)
|
61
58
|
begin
|
62
59
|
parse_time string
|
63
60
|
rescue ArgumentError
|
64
61
|
string
|
65
62
|
end
|
66
|
-
|
67
|
-
require 'date'
|
63
|
+
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
|
68
64
|
begin
|
69
|
-
class_loader.date.strptime(string, '%
|
65
|
+
class_loader.date.strptime(string, '%F', Date::GREGORIAN)
|
70
66
|
rescue ArgumentError
|
71
67
|
string
|
72
68
|
end
|
73
|
-
|
69
|
+
elsif string.match?(/^\+?\.inf$/i)
|
74
70
|
Float::INFINITY
|
75
|
-
|
71
|
+
elsif string.match?(/^-\.inf$/i)
|
76
72
|
-Float::INFINITY
|
77
|
-
|
73
|
+
elsif string.match?(/^\.nan$/i)
|
78
74
|
Float::NAN
|
79
|
-
|
75
|
+
elsif string.match?(/^:./)
|
80
76
|
if string =~ /^:(["'])(.*)\1/
|
81
77
|
@symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
|
82
78
|
else
|
83
79
|
@symbol_cache[string] = class_loader.symbolize(string.sub(/^:/, ''))
|
84
80
|
end
|
85
|
-
|
81
|
+
elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}$/)
|
86
82
|
i = 0
|
87
83
|
string.split(':').each_with_index do |n,e|
|
88
84
|
i += (n.to_i * 60 ** (e - 2).abs)
|
89
85
|
end
|
90
86
|
i
|
91
|
-
|
87
|
+
elsif string.match?(/^[-+]?[0-9][0-9_]*(:[0-5]?[0-9]){1,2}\.[0-9_]*$/)
|
92
88
|
i = 0
|
93
89
|
string.split(':').each_with_index do |n,e|
|
94
90
|
i += (n.to_f * 60 ** (e - 2).abs)
|
95
91
|
end
|
96
92
|
i
|
97
|
-
|
98
|
-
if string
|
99
|
-
@string_cache[string] = true
|
93
|
+
elsif string.match?(FLOAT)
|
94
|
+
if string.match?(/\A[-+]?\.\Z/)
|
100
95
|
string
|
101
96
|
else
|
102
|
-
Float(string.
|
97
|
+
Float(string.delete(',_').gsub(/\.([Ee]|$)/, '\1'))
|
103
98
|
end
|
99
|
+
elsif string.match?(integer_regex)
|
100
|
+
parse_int string
|
104
101
|
else
|
105
|
-
int = parse_int string.gsub(/[,_]/, '')
|
106
|
-
return int if int
|
107
|
-
|
108
|
-
@string_cache[string] = true
|
109
102
|
string
|
110
103
|
end
|
111
104
|
end
|
@@ -113,8 +106,7 @@ module Psych
|
|
113
106
|
###
|
114
107
|
# Parse and return an int from +string+
|
115
108
|
def parse_int string
|
116
|
-
|
117
|
-
Integer(string)
|
109
|
+
Integer(string.delete(',_'))
|
118
110
|
end
|
119
111
|
|
120
112
|
###
|
data/lib/psych/syntax_error.rb
CHANGED
data/lib/psych/tree_builder.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
require_relative 'handler'
|
3
3
|
|
4
4
|
module Psych
|
5
5
|
###
|
@@ -41,7 +41,7 @@ module Psych
|
|
41
41
|
Sequence
|
42
42
|
Mapping
|
43
43
|
}.each do |node|
|
44
|
-
class_eval
|
44
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
45
45
|
def start_#{node.downcase}(anchor, tag, implicit, style)
|
46
46
|
n = Nodes::#{node}.new(anchor, tag, implicit, style)
|
47
47
|
set_start_location(n)
|
@@ -54,7 +54,7 @@ module Psych
|
|
54
54
|
set_end_location(n)
|
55
55
|
n
|
56
56
|
end
|
57
|
-
|
57
|
+
RUBY
|
58
58
|
end
|
59
59
|
|
60
60
|
###
|
data/lib/psych/versions.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
|
2
1
|
# frozen_string_literal: true
|
2
|
+
|
3
3
|
module Psych
|
4
4
|
# The version of Psych you are using
|
5
|
-
VERSION = '
|
5
|
+
VERSION = '5.2.3'
|
6
6
|
|
7
7
|
if RUBY_ENGINE == 'jruby'
|
8
|
-
DEFAULT_SNAKEYAML_VERSION = '
|
8
|
+
DEFAULT_SNAKEYAML_VERSION = '2.9'.freeze
|
9
9
|
end
|
10
10
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
require_relative '../scalar_scanner'
|
3
|
+
require_relative '../class_loader'
|
4
|
+
require_relative '../exception'
|
5
5
|
|
6
6
|
unless defined?(Regexp::NOENCODING)
|
7
7
|
Regexp::NOENCODING = 32
|
@@ -12,39 +12,44 @@ module Psych
|
|
12
12
|
###
|
13
13
|
# This class walks a YAML AST, converting each node to Ruby
|
14
14
|
class ToRuby < Psych::Visitors::Visitor
|
15
|
-
def self.create
|
15
|
+
def self.create(symbolize_names: false, freeze: false, strict_integer: false)
|
16
16
|
class_loader = ClassLoader.new
|
17
|
-
scanner = ScalarScanner.new class_loader
|
18
|
-
new(scanner, class_loader)
|
17
|
+
scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
|
18
|
+
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
|
19
19
|
end
|
20
20
|
|
21
21
|
attr_reader :class_loader
|
22
22
|
|
23
|
-
def initialize ss, class_loader
|
23
|
+
def initialize ss, class_loader, symbolize_names: false, freeze: false
|
24
24
|
super()
|
25
25
|
@st = {}
|
26
26
|
@ss = ss
|
27
|
+
@load_tags = Psych.load_tags
|
27
28
|
@domain_types = Psych.domain_types
|
28
29
|
@class_loader = class_loader
|
30
|
+
@symbolize_names = symbolize_names
|
31
|
+
@freeze = freeze
|
29
32
|
end
|
30
33
|
|
31
34
|
def accept target
|
32
35
|
result = super
|
33
|
-
return result if @domain_types.empty? || !target.tag
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
+
unless @domain_types.empty? || !target.tag
|
38
|
+
key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
|
39
|
+
key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/)
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
+
if @domain_types.key? key
|
42
|
+
value, block = @domain_types[key]
|
43
|
+
result = block.call value, result
|
44
|
+
end
|
41
45
|
end
|
42
46
|
|
47
|
+
result = deduplicate(result).freeze if @freeze
|
43
48
|
result
|
44
49
|
end
|
45
50
|
|
46
51
|
def deserialize o
|
47
|
-
if klass = resolve_class(
|
52
|
+
if klass = resolve_class(@load_tags[o.tag])
|
48
53
|
instance = klass.allocate
|
49
54
|
|
50
55
|
if instance.respond_to?(:init_with)
|
@@ -74,8 +79,9 @@ module Psych
|
|
74
79
|
class_loader.big_decimal._load o.value
|
75
80
|
when "!ruby/object:DateTime"
|
76
81
|
class_loader.date_time
|
77
|
-
|
78
|
-
|
82
|
+
t = @ss.parse_time(o.value)
|
83
|
+
DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
|
84
|
+
(t.subsec/86400)
|
79
85
|
when '!ruby/encoding'
|
80
86
|
::Encoding.find o.value
|
81
87
|
when "!ruby/object:Complex"
|
@@ -94,7 +100,7 @@ module Psych
|
|
94
100
|
source = $1
|
95
101
|
options = 0
|
96
102
|
lang = nil
|
97
|
-
|
103
|
+
$2&.each_char do |option|
|
98
104
|
case option
|
99
105
|
when 'x' then options |= Regexp::EXTENDED
|
100
106
|
when 'i' then options |= Regexp::IGNORECASE
|
@@ -124,7 +130,7 @@ module Psych
|
|
124
130
|
end
|
125
131
|
|
126
132
|
def visit_Psych_Nodes_Sequence o
|
127
|
-
if klass = resolve_class(
|
133
|
+
if klass = resolve_class(@load_tags[o.tag])
|
128
134
|
instance = klass.allocate
|
129
135
|
|
130
136
|
if instance.respond_to?(:init_with)
|
@@ -156,8 +162,8 @@ module Psych
|
|
156
162
|
end
|
157
163
|
|
158
164
|
def visit_Psych_Nodes_Mapping o
|
159
|
-
if
|
160
|
-
return revive(resolve_class(
|
165
|
+
if @load_tags[o.tag]
|
166
|
+
return revive(resolve_class(@load_tags[o.tag]), o)
|
161
167
|
end
|
162
168
|
return revive_hash(register(o, {}), o) unless o.tag
|
163
169
|
|
@@ -252,6 +258,8 @@ module Psych
|
|
252
258
|
|
253
259
|
e = build_exception((resolve_class($1) || class_loader.exception),
|
254
260
|
h.delete('message'))
|
261
|
+
|
262
|
+
e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
|
255
263
|
init_with(e, h, o)
|
256
264
|
|
257
265
|
when '!set', 'tag:yaml.org,2002:set'
|
@@ -316,10 +324,11 @@ module Psych
|
|
316
324
|
end
|
317
325
|
|
318
326
|
def visit_Psych_Nodes_Alias o
|
319
|
-
@st.fetch(o.anchor) { raise
|
327
|
+
@st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
|
320
328
|
end
|
321
329
|
|
322
330
|
private
|
331
|
+
|
323
332
|
def register node, object
|
324
333
|
@st[node.anchor] = object if node.anchor
|
325
334
|
object
|
@@ -331,13 +340,12 @@ module Psych
|
|
331
340
|
list
|
332
341
|
end
|
333
342
|
|
334
|
-
|
335
|
-
def revive_hash hash, o
|
343
|
+
def revive_hash hash, o, tagged= false
|
336
344
|
o.children.each_slice(2) { |k,v|
|
337
345
|
key = accept(k)
|
338
346
|
val = accept(v)
|
339
347
|
|
340
|
-
if key ==
|
348
|
+
if key == '<<' && k.tag != "tag:yaml.org,2002:str"
|
341
349
|
case v
|
342
350
|
when Nodes::Alias, Nodes::Mapping
|
343
351
|
begin
|
@@ -359,6 +367,12 @@ module Psych
|
|
359
367
|
hash[key] = val
|
360
368
|
end
|
361
369
|
else
|
370
|
+
if !tagged && @symbolize_names && key.is_a?(String)
|
371
|
+
key = key.to_sym
|
372
|
+
elsif !@freeze
|
373
|
+
key = deduplicate(key)
|
374
|
+
end
|
375
|
+
|
362
376
|
hash[key] = val
|
363
377
|
end
|
364
378
|
|
@@ -366,12 +380,32 @@ module Psych
|
|
366
380
|
hash
|
367
381
|
end
|
368
382
|
|
383
|
+
if RUBY_VERSION < '2.7'
|
384
|
+
def deduplicate key
|
385
|
+
if key.is_a?(String)
|
386
|
+
# It is important to untaint the string, otherwise it won't
|
387
|
+
# be deduplicated into an fstring, but simply frozen.
|
388
|
+
-(key.untaint)
|
389
|
+
else
|
390
|
+
key
|
391
|
+
end
|
392
|
+
end
|
393
|
+
else
|
394
|
+
def deduplicate key
|
395
|
+
if key.is_a?(String)
|
396
|
+
-key
|
397
|
+
else
|
398
|
+
key
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
369
403
|
def merge_key hash, key, val
|
370
404
|
end
|
371
405
|
|
372
406
|
def revive klass, node
|
373
407
|
s = register(node, klass.allocate)
|
374
|
-
init_with(s, revive_hash({}, node), node)
|
408
|
+
init_with(s, revive_hash({}, node, true), node)
|
375
409
|
end
|
376
410
|
|
377
411
|
def init_with o, h, node
|
@@ -394,7 +428,7 @@ module Psych
|
|
394
428
|
|
395
429
|
class NoAliasRuby < ToRuby
|
396
430
|
def visit_Psych_Nodes_Alias o
|
397
|
-
raise
|
431
|
+
raise AliasesNotEnabled
|
398
432
|
end
|
399
433
|
end
|
400
434
|
end
|