psych 3.1.0 → 3.3.4
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/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +2 -5
- data/Rakefile +8 -15
- data/ext/psych/depend +2 -0
- data/ext/psych/extconf.rb +6 -2
- data/ext/psych/psych.c +6 -3
- data/ext/psych/psych_parser.c +20 -33
- data/ext/psych/psych_yaml_tree.c +0 -12
- data/ext/psych/yaml/api.c +22 -22
- data/ext/psych/yaml/config.h +76 -6
- data/ext/psych/yaml/dumper.c +1 -1
- data/ext/psych/yaml/emitter.c +44 -10
- data/ext/psych/yaml/loader.c +206 -106
- data/ext/psych/yaml/parser.c +6 -1
- data/ext/psych/yaml/scanner.c +45 -25
- data/ext/psych/yaml/yaml.h +43 -29
- data/ext/psych/yaml/yaml_private.h +4 -4
- data/lib/psych/class_loader.rb +6 -4
- data/lib/psych/handler.rb +1 -1
- data/lib/psych/nodes/node.rb +2 -2
- data/lib/psych/nodes/scalar.rb +1 -1
- data/lib/psych/scalar_scanner.rb +24 -37
- data/lib/psych/versions.rb +3 -3
- data/lib/psych/visitors/to_ruby.rb +53 -18
- data/lib/psych/visitors/visitor.rb +17 -3
- data/lib/psych/visitors/yaml_tree.rb +40 -52
- data/lib/psych.rb +72 -48
- data/psych.gemspec +8 -16
- metadata +9 -54
- data/.travis.yml +0 -22
- data/CHANGELOG.rdoc +0 -583
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 = '3.
|
5
|
+
VERSION = '3.3.4'
|
6
6
|
|
7
7
|
if RUBY_ENGINE == 'jruby'
|
8
|
-
DEFAULT_SNAKEYAML_VERSION = '1.
|
8
|
+
DEFAULT_SNAKEYAML_VERSION = '1.33'.freeze
|
9
9
|
end
|
10
10
|
end
|
@@ -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)
|
16
16
|
class_loader = ClassLoader.new
|
17
17
|
scanner = ScalarScanner.new class_loader
|
18
|
-
new(scanner, class_loader)
|
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 =~ /^(?: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)
|
@@ -75,7 +80,9 @@ module Psych
|
|
75
80
|
when "!ruby/object:DateTime"
|
76
81
|
class_loader.date_time
|
77
82
|
require 'date' unless defined? DateTime
|
78
|
-
@ss.parse_time(o.value)
|
83
|
+
t = @ss.parse_time(o.value)
|
84
|
+
DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
|
85
|
+
(t.subsec/86400)
|
79
86
|
when '!ruby/encoding'
|
80
87
|
::Encoding.find o.value
|
81
88
|
when "!ruby/object:Complex"
|
@@ -124,7 +131,7 @@ module Psych
|
|
124
131
|
end
|
125
132
|
|
126
133
|
def visit_Psych_Nodes_Sequence o
|
127
|
-
if klass = resolve_class(
|
134
|
+
if klass = resolve_class(@load_tags[o.tag])
|
128
135
|
instance = klass.allocate
|
129
136
|
|
130
137
|
if instance.respond_to?(:init_with)
|
@@ -156,8 +163,8 @@ module Psych
|
|
156
163
|
end
|
157
164
|
|
158
165
|
def visit_Psych_Nodes_Mapping o
|
159
|
-
if
|
160
|
-
return revive(resolve_class(
|
166
|
+
if @load_tags[o.tag]
|
167
|
+
return revive(resolve_class(@load_tags[o.tag]), o)
|
161
168
|
end
|
162
169
|
return revive_hash(register(o, {}), o) unless o.tag
|
163
170
|
|
@@ -252,6 +259,8 @@ module Psych
|
|
252
259
|
|
253
260
|
e = build_exception((resolve_class($1) || class_loader.exception),
|
254
261
|
h.delete('message'))
|
262
|
+
|
263
|
+
e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
|
255
264
|
init_with(e, h, o)
|
256
265
|
|
257
266
|
when '!set', 'tag:yaml.org,2002:set'
|
@@ -320,6 +329,7 @@ module Psych
|
|
320
329
|
end
|
321
330
|
|
322
331
|
private
|
332
|
+
|
323
333
|
def register node, object
|
324
334
|
@st[node.anchor] = object if node.anchor
|
325
335
|
object
|
@@ -331,13 +341,12 @@ module Psych
|
|
331
341
|
list
|
332
342
|
end
|
333
343
|
|
334
|
-
|
335
|
-
def revive_hash hash, o
|
344
|
+
def revive_hash hash, o, tagged= false
|
336
345
|
o.children.each_slice(2) { |k,v|
|
337
346
|
key = accept(k)
|
338
347
|
val = accept(v)
|
339
348
|
|
340
|
-
if key ==
|
349
|
+
if key == '<<' && k.tag != "tag:yaml.org,2002:str"
|
341
350
|
case v
|
342
351
|
when Nodes::Alias, Nodes::Mapping
|
343
352
|
begin
|
@@ -359,6 +368,12 @@ module Psych
|
|
359
368
|
hash[key] = val
|
360
369
|
end
|
361
370
|
else
|
371
|
+
if !tagged && @symbolize_names && key.is_a?(String)
|
372
|
+
key = key.to_sym
|
373
|
+
elsif !@freeze
|
374
|
+
key = deduplicate(key)
|
375
|
+
end
|
376
|
+
|
362
377
|
hash[key] = val
|
363
378
|
end
|
364
379
|
|
@@ -366,12 +381,32 @@ module Psych
|
|
366
381
|
hash
|
367
382
|
end
|
368
383
|
|
384
|
+
if RUBY_VERSION < '2.7'
|
385
|
+
def deduplicate key
|
386
|
+
if key.is_a?(String)
|
387
|
+
# It is important to untaint the string, otherwise it won't
|
388
|
+
# be deduplicated into an fstring, but simply frozen.
|
389
|
+
-(key.untaint)
|
390
|
+
else
|
391
|
+
key
|
392
|
+
end
|
393
|
+
end
|
394
|
+
else
|
395
|
+
def deduplicate key
|
396
|
+
if key.is_a?(String)
|
397
|
+
-key
|
398
|
+
else
|
399
|
+
key
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
369
404
|
def merge_key hash, key, val
|
370
405
|
end
|
371
406
|
|
372
407
|
def revive klass, node
|
373
408
|
s = register(node, klass.allocate)
|
374
|
-
init_with(s, revive_hash({}, node), node)
|
409
|
+
init_with(s, revive_hash({}, node, true), node)
|
375
410
|
end
|
376
411
|
|
377
412
|
def init_with o, h, node
|
@@ -8,12 +8,26 @@ module Psych
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# @api private
|
12
|
+
def self.dispatch_cache
|
13
|
+
Hash.new do |hash, klass|
|
14
|
+
hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
|
15
|
+
end.compare_by_identity
|
16
|
+
end
|
17
|
+
|
18
|
+
if defined?(Ractor)
|
19
|
+
def dispatch
|
20
|
+
@dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache)
|
21
|
+
end
|
22
|
+
else
|
23
|
+
DISPATCH = dispatch_cache
|
24
|
+
def dispatch
|
25
|
+
DISPATCH
|
26
|
+
end
|
13
27
|
end
|
14
28
|
|
15
29
|
def visit target
|
16
|
-
send
|
30
|
+
send dispatch[target.class], target
|
17
31
|
end
|
18
32
|
end
|
19
33
|
end
|
@@ -80,7 +80,7 @@ module Psych
|
|
80
80
|
raise(TypeError, "Can't dump #{target.class}") unless method
|
81
81
|
|
82
82
|
h[klass] = method
|
83
|
-
end
|
83
|
+
end.compare_by_identity
|
84
84
|
end
|
85
85
|
|
86
86
|
def start encoding = Nodes::Stream::UTF8
|
@@ -181,53 +181,24 @@ module Psych
|
|
181
181
|
end
|
182
182
|
|
183
183
|
def visit_Exception o
|
184
|
-
|
185
|
-
|
186
|
-
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
|
187
|
-
|
188
|
-
{
|
189
|
-
'message' => private_iv_get(o, 'mesg'),
|
190
|
-
'backtrace' => private_iv_get(o, 'backtrace'),
|
191
|
-
}.each do |k,v|
|
192
|
-
next unless v
|
193
|
-
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
|
194
|
-
accept v
|
195
|
-
end
|
196
|
-
|
197
|
-
dump_ivars o
|
198
|
-
|
199
|
-
@emitter.end_mapping
|
184
|
+
dump_exception o, o.message.to_s
|
200
185
|
end
|
201
186
|
|
202
187
|
def visit_NameError o
|
203
|
-
|
204
|
-
|
205
|
-
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
|
206
|
-
|
207
|
-
{
|
208
|
-
'message' => o.message.to_s,
|
209
|
-
'backtrace' => private_iv_get(o, 'backtrace'),
|
210
|
-
}.each do |k,v|
|
211
|
-
next unless v
|
212
|
-
@emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
|
213
|
-
accept v
|
214
|
-
end
|
215
|
-
|
216
|
-
dump_ivars o
|
217
|
-
|
218
|
-
@emitter.end_mapping
|
188
|
+
dump_exception o, o.message.to_s
|
219
189
|
end
|
220
190
|
|
221
191
|
def visit_Regexp o
|
222
192
|
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
|
223
193
|
end
|
224
194
|
|
195
|
+
def visit_Date o
|
196
|
+
register o, visit_Integer(o.gregorian)
|
197
|
+
end
|
198
|
+
|
225
199
|
def visit_DateTime o
|
226
|
-
|
227
|
-
|
228
|
-
else
|
229
|
-
o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
|
230
|
-
end
|
200
|
+
t = o.italy
|
201
|
+
formatted = format_time t, t.offset.zero?
|
231
202
|
tag = '!ruby/object:DateTime'
|
232
203
|
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
|
233
204
|
end
|
@@ -265,7 +236,6 @@ module Psych
|
|
265
236
|
end
|
266
237
|
alias :visit_TrueClass :visit_Integer
|
267
238
|
alias :visit_FalseClass :visit_Integer
|
268
|
-
alias :visit_Date :visit_Integer
|
269
239
|
|
270
240
|
def visit_Float o
|
271
241
|
if o.nan?
|
@@ -458,15 +428,6 @@ module Psych
|
|
458
428
|
node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
|
459
429
|
register(o, node)
|
460
430
|
|
461
|
-
# Dump the elements
|
462
|
-
accept 'elements'
|
463
|
-
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
|
464
|
-
o.each do |k,v|
|
465
|
-
accept k
|
466
|
-
accept v
|
467
|
-
end
|
468
|
-
@emitter.end_mapping
|
469
|
-
|
470
431
|
# Dump the ivars
|
471
432
|
accept 'ivars'
|
472
433
|
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
|
@@ -476,6 +437,15 @@ module Psych
|
|
476
437
|
end
|
477
438
|
@emitter.end_mapping
|
478
439
|
|
440
|
+
# Dump the elements
|
441
|
+
accept 'elements'
|
442
|
+
@emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
|
443
|
+
o.each do |k,v|
|
444
|
+
accept k
|
445
|
+
accept v
|
446
|
+
end
|
447
|
+
@emitter.end_mapping
|
448
|
+
|
479
449
|
@emitter.end_mapping
|
480
450
|
else
|
481
451
|
tag = "!ruby/hash:#{o.class}"
|
@@ -492,8 +462,26 @@ module Psych
|
|
492
462
|
def dump_list o
|
493
463
|
end
|
494
464
|
|
495
|
-
def
|
496
|
-
|
465
|
+
def dump_exception o, msg
|
466
|
+
tag = ['!ruby/exception', o.class.name].join ':'
|
467
|
+
|
468
|
+
@emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
|
469
|
+
|
470
|
+
if msg
|
471
|
+
@emitter.scalar 'message', nil, nil, true, false, Nodes::Scalar::ANY
|
472
|
+
accept msg
|
473
|
+
end
|
474
|
+
|
475
|
+
@emitter.scalar 'backtrace', nil, nil, true, false, Nodes::Scalar::ANY
|
476
|
+
accept o.backtrace
|
477
|
+
|
478
|
+
dump_ivars o
|
479
|
+
|
480
|
+
@emitter.end_mapping
|
481
|
+
end
|
482
|
+
|
483
|
+
def format_time time, utc = time.utc?
|
484
|
+
if utc
|
497
485
|
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
|
498
486
|
else
|
499
487
|
time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
|
@@ -521,9 +509,9 @@ module Psych
|
|
521
509
|
def emit_coder c, o
|
522
510
|
case c.type
|
523
511
|
when :scalar
|
524
|
-
@emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false,
|
512
|
+
@emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style
|
525
513
|
when :seq
|
526
|
-
@emitter.start_sequence nil, c.tag, c.tag.nil?,
|
514
|
+
@emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
|
527
515
|
c.seq.each do |thing|
|
528
516
|
accept thing
|
529
517
|
end
|
data/lib/psych.rb
CHANGED
@@ -10,11 +10,7 @@ when 'jruby'
|
|
10
10
|
org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
|
11
11
|
end
|
12
12
|
else
|
13
|
-
|
14
|
-
require "#{RUBY_VERSION[/\d+\.\d+/]}/psych.so"
|
15
|
-
rescue LoadError
|
16
|
-
require 'psych.so'
|
17
|
-
end
|
13
|
+
require 'psych.so'
|
18
14
|
end
|
19
15
|
require 'psych/nodes'
|
20
16
|
require 'psych/streaming'
|
@@ -78,12 +74,15 @@ require 'psych/class_loader'
|
|
78
74
|
#
|
79
75
|
# ==== Reading from a string
|
80
76
|
#
|
81
|
-
# Psych.
|
82
|
-
# Psych.
|
77
|
+
# Psych.safe_load("--- a") # => 'a'
|
78
|
+
# Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
|
79
|
+
# # From a trusted string:
|
80
|
+
# Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
|
83
81
|
#
|
84
82
|
# ==== Reading from a file
|
85
83
|
#
|
86
|
-
# Psych.
|
84
|
+
# Psych.safe_load_file("data.yml", permitted_classes: [Date])
|
85
|
+
# Psych.load_file("trusted_database.yml")
|
87
86
|
#
|
88
87
|
# ==== Exception handling
|
89
88
|
#
|
@@ -234,9 +233,9 @@ require 'psych/class_loader'
|
|
234
233
|
|
235
234
|
module Psych
|
236
235
|
# The version of libyaml Psych is using
|
237
|
-
LIBYAML_VERSION = Psych.libyaml_version.join
|
236
|
+
LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze
|
238
237
|
# Deprecation guard
|
239
|
-
NOT_GIVEN = Object.new
|
238
|
+
NOT_GIVEN = Object.new.freeze
|
240
239
|
private_constant :NOT_GIVEN
|
241
240
|
|
242
241
|
###
|
@@ -268,7 +267,11 @@ module Psych
|
|
268
267
|
#
|
269
268
|
# Raises a TypeError when `yaml` parameter is NilClass
|
270
269
|
#
|
271
|
-
|
270
|
+
# NOTE: This method *should not* be used to parse untrusted documents, such as
|
271
|
+
# YAML documents that are supplied via user input. Instead, please use the
|
272
|
+
# safe_load method.
|
273
|
+
#
|
274
|
+
def self.unsafe_load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false
|
272
275
|
if legacy_filename != NOT_GIVEN
|
273
276
|
warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
|
274
277
|
filename = legacy_filename
|
@@ -276,10 +279,9 @@ module Psych
|
|
276
279
|
|
277
280
|
result = parse(yaml, filename: filename)
|
278
281
|
return fallback unless result
|
279
|
-
result
|
280
|
-
symbolize_names!(result) if symbolize_names
|
281
|
-
result
|
282
|
+
result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
|
282
283
|
end
|
284
|
+
class << self; alias :load :unsafe_load; end
|
283
285
|
|
284
286
|
###
|
285
287
|
# Safely load the yaml string in +yaml+. By default, only the following
|
@@ -325,7 +327,7 @@ module Psych
|
|
325
327
|
# Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
|
326
328
|
# Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
|
327
329
|
#
|
328
|
-
def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false
|
330
|
+
def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
|
329
331
|
if legacy_permitted_classes != NOT_GIVEN
|
330
332
|
warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE
|
331
333
|
permitted_classes = legacy_permitted_classes
|
@@ -353,12 +355,11 @@ module Psych
|
|
353
355
|
permitted_symbols.map(&:to_s))
|
354
356
|
scanner = ScalarScanner.new class_loader
|
355
357
|
visitor = if aliases
|
356
|
-
Visitors::ToRuby.new scanner, class_loader
|
358
|
+
Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
|
357
359
|
else
|
358
|
-
Visitors::NoAliasRuby.new scanner, class_loader
|
360
|
+
Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
|
359
361
|
end
|
360
362
|
result = visitor.accept result
|
361
|
-
symbolize_names!(result) if symbolize_names
|
362
363
|
result
|
363
364
|
end
|
364
365
|
|
@@ -551,7 +552,7 @@ module Psych
|
|
551
552
|
# end
|
552
553
|
# list # => ['foo', 'bar']
|
553
554
|
#
|
554
|
-
def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: []
|
555
|
+
def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs
|
555
556
|
if legacy_filename != NOT_GIVEN
|
556
557
|
warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
|
557
558
|
filename = legacy_filename
|
@@ -559,10 +560,10 @@ module Psych
|
|
559
560
|
|
560
561
|
result = if block_given?
|
561
562
|
parse_stream(yaml, filename: filename) do |node|
|
562
|
-
yield node.to_ruby
|
563
|
+
yield node.to_ruby(**kwargs)
|
563
564
|
end
|
564
565
|
else
|
565
|
-
parse_stream(yaml, filename: filename).children.map(
|
566
|
+
parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
|
566
567
|
end
|
567
568
|
|
568
569
|
return fallback if result.is_a?(Array) && result.empty?
|
@@ -573,50 +574,50 @@ module Psych
|
|
573
574
|
# Load the document contained in +filename+. Returns the yaml contained in
|
574
575
|
# +filename+ as a Ruby object, or if the file is empty, it returns
|
575
576
|
# the specified +fallback+ return value, which defaults to +false+.
|
576
|
-
|
577
|
+
#
|
578
|
+
# NOTE: This method *should not* be used to parse untrusted documents, such as
|
579
|
+
# YAML documents that are supplied via user input. Instead, please use the
|
580
|
+
# safe_load_file method.
|
581
|
+
def self.unsafe_load_file filename, **kwargs
|
582
|
+
File.open(filename, 'r:bom|utf-8') { |f|
|
583
|
+
self.unsafe_load f, filename: filename, **kwargs
|
584
|
+
}
|
585
|
+
end
|
586
|
+
class << self; alias :load_file :unsafe_load_file; end
|
587
|
+
|
588
|
+
###
|
589
|
+
# Safely loads the document contained in +filename+. Returns the yaml contained in
|
590
|
+
# +filename+ as a Ruby object, or if the file is empty, it returns
|
591
|
+
# the specified +fallback+ return value, which defaults to +false+.
|
592
|
+
# See safe_load for options.
|
593
|
+
def self.safe_load_file filename, **kwargs
|
577
594
|
File.open(filename, 'r:bom|utf-8') { |f|
|
578
|
-
self.
|
595
|
+
self.safe_load f, filename: filename, **kwargs
|
579
596
|
}
|
580
597
|
end
|
581
598
|
|
582
599
|
# :stopdoc:
|
583
|
-
@domain_types = {}
|
584
600
|
def self.add_domain_type domain, type_tag, &block
|
585
601
|
key = ['tag', domain, type_tag].join ':'
|
586
|
-
|
587
|
-
|
602
|
+
domain_types[key] = [key, block]
|
603
|
+
domain_types["tag:#{type_tag}"] = [key, block]
|
588
604
|
end
|
589
605
|
|
590
606
|
def self.add_builtin_type type_tag, &block
|
591
607
|
domain = 'yaml.org,2002'
|
592
608
|
key = ['tag', domain, type_tag].join ':'
|
593
|
-
|
609
|
+
domain_types[key] = [key, block]
|
594
610
|
end
|
595
611
|
|
596
612
|
def self.remove_type type_tag
|
597
|
-
|
613
|
+
domain_types.delete type_tag
|
598
614
|
end
|
599
615
|
|
600
|
-
@load_tags = {}
|
601
|
-
@dump_tags = {}
|
602
616
|
def self.add_tag tag, klass
|
603
|
-
|
604
|
-
|
617
|
+
load_tags[tag] = klass.name
|
618
|
+
dump_tags[klass] = tag
|
605
619
|
end
|
606
620
|
|
607
|
-
def self.symbolize_names!(result)
|
608
|
-
case result
|
609
|
-
when Hash
|
610
|
-
result.keys.each do |key|
|
611
|
-
result[key.to_sym] = symbolize_names!(result.delete(key))
|
612
|
-
end
|
613
|
-
when Array
|
614
|
-
result.map! { |r| symbolize_names!(r) }
|
615
|
-
end
|
616
|
-
result
|
617
|
-
end
|
618
|
-
private_class_method :symbolize_names!
|
619
|
-
|
620
621
|
# Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower.
|
621
622
|
def self.warn_with_uplevel(message, uplevel: 1)
|
622
623
|
at = parse_caller(caller[uplevel]).join(':')
|
@@ -633,9 +634,32 @@ module Psych
|
|
633
634
|
private_class_method :warn_with_uplevel, :parse_caller
|
634
635
|
|
635
636
|
class << self
|
636
|
-
|
637
|
-
|
638
|
-
|
637
|
+
if defined?(Ractor)
|
638
|
+
require 'forwardable'
|
639
|
+
extend Forwardable
|
640
|
+
|
641
|
+
class Config
|
642
|
+
attr_accessor :load_tags, :dump_tags, :domain_types
|
643
|
+
def initialize
|
644
|
+
@load_tags = {}
|
645
|
+
@dump_tags = {}
|
646
|
+
@domain_types = {}
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
650
|
+
def config
|
651
|
+
Ractor.current[:PsychConfig] ||= Config.new
|
652
|
+
end
|
653
|
+
|
654
|
+
def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types=
|
655
|
+
else
|
656
|
+
attr_accessor :load_tags
|
657
|
+
attr_accessor :dump_tags
|
658
|
+
attr_accessor :domain_types
|
659
|
+
end
|
639
660
|
end
|
661
|
+
self.load_tags = {}
|
662
|
+
self.dump_tags = {}
|
663
|
+
self.domain_types = {}
|
640
664
|
# :startdoc:
|
641
665
|
end
|
data/psych.gemspec
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# for Ruby core repository
|
8
|
-
require_relative 'versions'
|
4
|
+
version_module = Module.new do
|
5
|
+
version_rb = File.join(__dir__, "lib/psych/versions.rb")
|
6
|
+
module_eval(File.read(version_rb), version_rb)
|
9
7
|
end
|
10
8
|
|
11
9
|
Gem::Specification.new do |s|
|
12
10
|
s.name = "psych"
|
13
|
-
s.version = Psych::VERSION
|
11
|
+
s.version = version_module::Psych::VERSION
|
14
12
|
s.authors = ["Aaron Patterson", "SHIBATA Hiroshi", "Charles Oliver Nutter"]
|
15
13
|
s.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org", "headius@headius.com"]
|
16
14
|
s.summary = "Psych is a YAML parser and emitter"
|
@@ -25,7 +23,7 @@ DESCRIPTION
|
|
25
23
|
|
26
24
|
# for ruby core repository. It was generated by `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
25
|
s.files = [
|
28
|
-
".gitignore", "
|
26
|
+
".gitignore", "Gemfile", "LICENSE", "Mavenfile", "README.md", "Rakefile", "bin/console",
|
29
27
|
"bin/setup", "ext/psych/depend", "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h",
|
30
28
|
"ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h", "ext/psych/psych_parser.c", "ext/psych/psych_parser.h",
|
31
29
|
"ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h", "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h",
|
@@ -45,15 +43,11 @@ DESCRIPTION
|
|
45
43
|
]
|
46
44
|
|
47
45
|
s.rdoc_options = ["--main", "README.md"]
|
48
|
-
s.extra_rdoc_files = ["
|
46
|
+
s.extra_rdoc_files = ["README.md"]
|
49
47
|
|
50
|
-
s.required_ruby_version = Gem::Requirement.new(">= 2.
|
51
|
-
s.rubygems_version = "2.5.1"
|
48
|
+
s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
52
49
|
s.required_rubygems_version = Gem::Requirement.new(">= 0")
|
53
50
|
|
54
|
-
s.add_development_dependency 'rake-compiler', ">= 0.4.1"
|
55
|
-
s.add_development_dependency 'minitest', "~> 5.0"
|
56
|
-
|
57
51
|
if RUBY_ENGINE == 'jruby'
|
58
52
|
s.platform = 'java'
|
59
53
|
s.files.concat [
|
@@ -65,11 +59,9 @@ DESCRIPTION
|
|
65
59
|
"lib/psych_jars.rb",
|
66
60
|
"lib/psych.jar"
|
67
61
|
]
|
68
|
-
s.requirements = "jar org.yaml:snakeyaml, #{Psych::DEFAULT_SNAKEYAML_VERSION}"
|
62
|
+
s.requirements = "jar org.yaml:snakeyaml, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}"
|
69
63
|
s.add_dependency 'jar-dependencies', '>= 0.1.7'
|
70
|
-
s.add_development_dependency 'ruby-maven'
|
71
64
|
else
|
72
65
|
s.extensions = ["ext/psych/extconf.rb"]
|
73
|
-
s.add_development_dependency 'rake-compiler-dock', ">= 0.6.3"
|
74
66
|
end
|
75
67
|
end
|