psych 2.0.12 → 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.
Files changed (115) hide show
  1. checksums.yaml +5 -5
  2. data/CONTRIBUTING.md +24 -0
  3. data/{ext/psych/yaml/LICENSE → LICENSE} +9 -7
  4. data/README.md +80 -0
  5. data/ext/psych/depend +14 -0
  6. data/ext/psych/extconf.rb +43 -28
  7. data/ext/psych/psych.c +6 -4
  8. data/ext/psych/psych.h +0 -3
  9. data/ext/psych/psych_emitter.c +165 -132
  10. data/ext/psych/psych_parser.c +298 -331
  11. data/ext/psych/psych_to_ruby.c +0 -5
  12. data/ext/psych/psych_yaml_tree.c +0 -13
  13. data/lib/psych/class_loader.rb +11 -8
  14. data/lib/psych/coder.rb +1 -0
  15. data/lib/psych/core_ext.rb +3 -19
  16. data/lib/psych/exception.rb +17 -2
  17. data/lib/psych/handler.rb +8 -2
  18. data/lib/psych/handlers/document_stream.rb +2 -1
  19. data/lib/psych/handlers/recorder.rb +2 -1
  20. data/lib/psych/json/ruby_events.rb +1 -0
  21. data/lib/psych/json/stream.rb +3 -2
  22. data/lib/psych/json/tree_builder.rb +2 -1
  23. data/lib/psych/json/yaml_events.rb +1 -0
  24. data/lib/psych/nodes/alias.rb +3 -0
  25. data/lib/psych/nodes/document.rb +3 -0
  26. data/lib/psych/nodes/mapping.rb +3 -0
  27. data/lib/psych/nodes/node.rb +25 -5
  28. data/lib/psych/nodes/scalar.rb +4 -1
  29. data/lib/psych/nodes/sequence.rb +3 -0
  30. data/lib/psych/nodes/stream.rb +3 -0
  31. data/lib/psych/nodes.rb +8 -7
  32. data/lib/psych/omap.rb +1 -0
  33. data/lib/psych/parser.rb +14 -0
  34. data/lib/psych/scalar_scanner.rb +41 -49
  35. data/lib/psych/set.rb +1 -0
  36. data/lib/psych/stream.rb +1 -0
  37. data/lib/psych/streaming.rb +1 -0
  38. data/lib/psych/syntax_error.rb +2 -1
  39. data/lib/psych/tree_builder.rb +48 -7
  40. data/lib/psych/versions.rb +10 -0
  41. data/lib/psych/visitors/depth_first.rb +1 -0
  42. data/lib/psych/visitors/emitter.rb +1 -0
  43. data/lib/psych/visitors/json_tree.rb +2 -1
  44. data/lib/psych/visitors/to_ruby.rb +64 -33
  45. data/lib/psych/visitors/visitor.rb +18 -3
  46. data/lib/psych/visitors/yaml_tree.rb +128 -149
  47. data/lib/psych/visitors.rb +7 -6
  48. data/lib/psych/y.rb +1 -0
  49. data/lib/psych.rb +360 -95
  50. metadata +36 -169
  51. data/.autotest +0 -18
  52. data/.gemtest +0 -0
  53. data/.travis.yml +0 -11
  54. data/CHANGELOG.rdoc +0 -562
  55. data/Manifest.txt +0 -112
  56. data/README.rdoc +0 -71
  57. data/Rakefile +0 -74
  58. data/ext/psych/yaml/api.c +0 -1415
  59. data/ext/psych/yaml/config.h +0 -10
  60. data/ext/psych/yaml/dumper.c +0 -394
  61. data/ext/psych/yaml/emitter.c +0 -2329
  62. data/ext/psych/yaml/loader.c +0 -459
  63. data/ext/psych/yaml/parser.c +0 -1370
  64. data/ext/psych/yaml/reader.c +0 -469
  65. data/ext/psych/yaml/scanner.c +0 -3583
  66. data/ext/psych/yaml/writer.c +0 -141
  67. data/ext/psych/yaml/yaml.h +0 -1971
  68. data/ext/psych/yaml/yaml_private.h +0 -664
  69. data/lib/psych/deprecated.rb +0 -85
  70. data/test/psych/handlers/test_recorder.rb +0 -25
  71. data/test/psych/helper.rb +0 -114
  72. data/test/psych/json/test_stream.rb +0 -109
  73. data/test/psych/nodes/test_enumerable.rb +0 -43
  74. data/test/psych/test_alias_and_anchor.rb +0 -96
  75. data/test/psych/test_array.rb +0 -57
  76. data/test/psych/test_boolean.rb +0 -36
  77. data/test/psych/test_class.rb +0 -36
  78. data/test/psych/test_coder.rb +0 -184
  79. data/test/psych/test_date_time.rb +0 -38
  80. data/test/psych/test_deprecated.rb +0 -214
  81. data/test/psych/test_document.rb +0 -46
  82. data/test/psych/test_emitter.rb +0 -93
  83. data/test/psych/test_encoding.rb +0 -259
  84. data/test/psych/test_exception.rb +0 -157
  85. data/test/psych/test_hash.rb +0 -94
  86. data/test/psych/test_json_tree.rb +0 -65
  87. data/test/psych/test_marshalable.rb +0 -54
  88. data/test/psych/test_merge_keys.rb +0 -180
  89. data/test/psych/test_nil.rb +0 -18
  90. data/test/psych/test_null.rb +0 -19
  91. data/test/psych/test_numeric.rb +0 -45
  92. data/test/psych/test_object.rb +0 -44
  93. data/test/psych/test_object_references.rb +0 -71
  94. data/test/psych/test_omap.rb +0 -75
  95. data/test/psych/test_parser.rb +0 -339
  96. data/test/psych/test_psych.rb +0 -168
  97. data/test/psych/test_safe_load.rb +0 -97
  98. data/test/psych/test_scalar.rb +0 -11
  99. data/test/psych/test_scalar_scanner.rb +0 -106
  100. data/test/psych/test_serialize_subclasses.rb +0 -38
  101. data/test/psych/test_set.rb +0 -49
  102. data/test/psych/test_stream.rb +0 -93
  103. data/test/psych/test_string.rb +0 -226
  104. data/test/psych/test_struct.rb +0 -49
  105. data/test/psych/test_symbol.rb +0 -25
  106. data/test/psych/test_tainted.rb +0 -130
  107. data/test/psych/test_to_yaml_properties.rb +0 -63
  108. data/test/psych/test_tree_builder.rb +0 -79
  109. data/test/psych/test_yaml.rb +0 -1288
  110. data/test/psych/test_yamldbm.rb +0 -193
  111. data/test/psych/test_yamlstore.rb +0 -85
  112. data/test/psych/visitors/test_depth_first.rb +0 -49
  113. data/test/psych/visitors/test_emitter.rb +0 -144
  114. data/test/psych/visitors/test_to_ruby.rb +0 -326
  115. data/test/psych/visitors/test_yaml_tree.rb +0 -173
@@ -1,4 +1,5 @@
1
- require 'psych/handler'
1
+ # frozen_string_literal: true
2
+ require_relative 'handler'
2
3
 
3
4
  module Psych
4
5
  ###
@@ -22,23 +23,38 @@ module Psych
22
23
  @stack = []
23
24
  @last = nil
24
25
  @root = nil
26
+
27
+ @start_line = nil
28
+ @start_column = nil
29
+ @end_line = nil
30
+ @end_column = nil
31
+ end
32
+
33
+ def event_location(start_line, start_column, end_line, end_column)
34
+ @start_line = start_line
35
+ @start_column = start_column
36
+ @end_line = end_line
37
+ @end_column = end_column
25
38
  end
26
39
 
27
40
  %w{
28
41
  Sequence
29
42
  Mapping
30
43
  }.each do |node|
31
- class_eval %{
44
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
32
45
  def start_#{node.downcase}(anchor, tag, implicit, style)
33
46
  n = Nodes::#{node}.new(anchor, tag, implicit, style)
47
+ set_start_location(n)
34
48
  @last.children << n
35
49
  push n
36
50
  end
37
51
 
38
52
  def end_#{node.downcase}
39
- pop
53
+ n = pop
54
+ set_end_location(n)
55
+ n
40
56
  end
41
- }
57
+ RUBY
42
58
  end
43
59
 
44
60
  ###
@@ -48,6 +64,7 @@ module Psych
48
64
  # See Psych::Handler#start_document
49
65
  def start_document version, tag_directives, implicit
50
66
  n = Nodes::Document.new version, tag_directives, implicit
67
+ set_start_location(n)
51
68
  @last.children << n
52
69
  push n
53
70
  end
@@ -59,26 +76,35 @@ module Psych
59
76
  # See Psych::Handler#start_document
60
77
  def end_document implicit_end = !streaming?
61
78
  @last.implicit_end = implicit_end
62
- pop
79
+ n = pop
80
+ set_end_location(n)
81
+ n
63
82
  end
64
83
 
65
84
  def start_stream encoding
66
85
  @root = Nodes::Stream.new(encoding)
86
+ set_start_location(@root)
67
87
  push @root
68
88
  end
69
89
 
70
90
  def end_stream
71
- pop
91
+ n = pop
92
+ set_end_location(n)
93
+ n
72
94
  end
73
95
 
74
96
  def scalar value, anchor, tag, plain, quoted, style
75
97
  s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
98
+ set_location(s)
76
99
  @last.children << s
77
100
  s
78
101
  end
79
102
 
80
103
  def alias anchor
81
- @last.children << Nodes::Alias.new(anchor)
104
+ a = Nodes::Alias.new(anchor)
105
+ set_location(a)
106
+ @last.children << a
107
+ a
82
108
  end
83
109
 
84
110
  private
@@ -92,5 +118,20 @@ module Psych
92
118
  @last = @stack.last
93
119
  x
94
120
  end
121
+
122
+ def set_location(node)
123
+ set_start_location(node)
124
+ set_end_location(node)
125
+ end
126
+
127
+ def set_start_location(node)
128
+ node.start_line = @start_line
129
+ node.start_column = @start_column
130
+ end
131
+
132
+ def set_end_location(node)
133
+ node.end_line = @end_line
134
+ node.end_column = @end_column
135
+ end
95
136
  end
96
137
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Psych
4
+ # The version of Psych you are using
5
+ VERSION = '5.2.3'
6
+
7
+ if RUBY_ENGINE == 'jruby'
8
+ DEFAULT_SNAKEYAML_VERSION = '2.9'.freeze
9
+ end
10
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Psych
2
3
  module Visitors
3
4
  class DepthFirst < Psych::Visitors::Visitor
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Psych
2
3
  module Visitors
3
4
  class Emitter < Psych::Visitors::Visitor
@@ -1,4 +1,5 @@
1
- require 'psych/json/ruby_events'
1
+ # frozen_string_literal: true
2
+ require_relative '../json/ruby_events'
2
3
 
3
4
  module Psych
4
5
  module Visitors
@@ -1,6 +1,7 @@
1
- require 'psych/scalar_scanner'
2
- require 'psych/class_loader'
3
- require 'psych/exception'
1
+ # frozen_string_literal: true
2
+ require_relative '../scalar_scanner'
3
+ require_relative '../class_loader'
4
+ require_relative '../exception'
4
5
 
5
6
  unless defined?(Regexp::NOENCODING)
6
7
  Regexp::NOENCODING = 32
@@ -11,39 +12,44 @@ module Psych
11
12
  ###
12
13
  # This class walks a YAML AST, converting each node to Ruby
13
14
  class ToRuby < Psych::Visitors::Visitor
14
- def self.create
15
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false)
15
16
  class_loader = ClassLoader.new
16
- scanner = ScalarScanner.new class_loader
17
- 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)
18
19
  end
19
20
 
20
21
  attr_reader :class_loader
21
22
 
22
- def initialize ss, class_loader
23
+ def initialize ss, class_loader, symbolize_names: false, freeze: false
23
24
  super()
24
25
  @st = {}
25
26
  @ss = ss
27
+ @load_tags = Psych.load_tags
26
28
  @domain_types = Psych.domain_types
27
29
  @class_loader = class_loader
30
+ @symbolize_names = symbolize_names
31
+ @freeze = freeze
28
32
  end
29
33
 
30
34
  def accept target
31
35
  result = super
32
- return result if @domain_types.empty? || !target.tag
33
36
 
34
- key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
35
- key = "tag:#{key}" unless key =~ /^(tag:|x-private)/
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)/)
36
40
 
37
- if @domain_types.key? key
38
- value, block = @domain_types[key]
39
- return block.call value, result
41
+ if @domain_types.key? key
42
+ value, block = @domain_types[key]
43
+ result = block.call value, result
44
+ end
40
45
  end
41
46
 
47
+ result = deduplicate(result).freeze if @freeze
42
48
  result
43
49
  end
44
50
 
45
51
  def deserialize o
46
- if klass = resolve_class(Psych.load_tags[o.tag])
52
+ if klass = resolve_class(@load_tags[o.tag])
47
53
  instance = klass.allocate
48
54
 
49
55
  if instance.respond_to?(:init_with)
@@ -61,7 +67,7 @@ module Psych
61
67
  case o.tag
62
68
  when '!binary', 'tag:yaml.org,2002:binary'
63
69
  o.value.unpack('m').first
64
- when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
70
+ when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
65
71
  klass = resolve_class($1)
66
72
  if klass
67
73
  klass.allocate.replace o.value
@@ -69,12 +75,13 @@ module Psych
69
75
  o.value
70
76
  end
71
77
  when '!ruby/object:BigDecimal'
72
- require 'bigdecimal'
78
+ require 'bigdecimal' unless defined? BigDecimal
73
79
  class_loader.big_decimal._load o.value
74
80
  when "!ruby/object:DateTime"
75
81
  class_loader.date_time
76
- require 'date'
77
- @ss.parse_time(o.value).to_datetime
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)
78
85
  when '!ruby/encoding'
79
86
  ::Encoding.find o.value
80
87
  when "!ruby/object:Complex"
@@ -89,11 +96,11 @@ module Psych
89
96
  Float(@ss.tokenize(o.value))
90
97
  when "!ruby/regexp"
91
98
  klass = class_loader.regexp
92
- o.value =~ /^\/(.*)\/([mixn]*)$/
99
+ o.value =~ /^\/(.*)\/([mixn]*)$/m
93
100
  source = $1
94
101
  options = 0
95
102
  lang = nil
96
- ($2 || '').split('').each do |option|
103
+ $2&.each_char do |option|
97
104
  case option
98
105
  when 'x' then options |= Regexp::EXTENDED
99
106
  when 'i' then options |= Regexp::IGNORECASE
@@ -123,7 +130,7 @@ module Psych
123
130
  end
124
131
 
125
132
  def visit_Psych_Nodes_Sequence o
126
- if klass = resolve_class(Psych.load_tags[o.tag])
133
+ if klass = resolve_class(@load_tags[o.tag])
127
134
  instance = klass.allocate
128
135
 
129
136
  if instance.respond_to?(:init_with)
@@ -155,8 +162,8 @@ module Psych
155
162
  end
156
163
 
157
164
  def visit_Psych_Nodes_Mapping o
158
- if Psych.load_tags[o.tag]
159
- return revive(resolve_class(Psych.load_tags[o.tag]), o)
165
+ if @load_tags[o.tag]
166
+ return revive(resolve_class(@load_tags[o.tag]), o)
160
167
  end
161
168
  return revive_hash(register(o, {}), o) unless o.tag
162
169
 
@@ -208,7 +215,7 @@ module Psych
208
215
  obj
209
216
  end
210
217
 
211
- when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
218
+ when /^!(?:str|ruby\/string)(?::(.*))?$/, 'tag:yaml.org,2002:str'
212
219
  klass = resolve_class($1)
213
220
  members = {}
214
221
  string = nil
@@ -251,6 +258,8 @@ module Psych
251
258
 
252
259
  e = build_exception((resolve_class($1) || class_loader.exception),
253
260
  h.delete('message'))
261
+
262
+ e.set_backtrace h.delete('backtrace') if h.key? 'backtrace'
254
263
  init_with(e, h, o)
255
264
 
256
265
  when '!set', 'tag:yaml.org,2002:set'
@@ -315,10 +324,11 @@ module Psych
315
324
  end
316
325
 
317
326
  def visit_Psych_Nodes_Alias o
318
- @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
327
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
319
328
  end
320
329
 
321
330
  private
331
+
322
332
  def register node, object
323
333
  @st[node.anchor] = object if node.anchor
324
334
  object
@@ -330,7 +340,7 @@ module Psych
330
340
  list
331
341
  end
332
342
 
333
- def revive_hash hash, o
343
+ def revive_hash hash, o, tagged= false
334
344
  o.children.each_slice(2) { |k,v|
335
345
  key = accept(k)
336
346
  val = accept(v)
@@ -357,6 +367,12 @@ module Psych
357
367
  hash[key] = val
358
368
  end
359
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
+
360
376
  hash[key] = val
361
377
  end
362
378
 
@@ -364,12 +380,32 @@ module Psych
364
380
  hash
365
381
  end
366
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
+
367
403
  def merge_key hash, key, val
368
404
  end
369
405
 
370
406
  def revive klass, node
371
407
  s = register(node, klass.allocate)
372
- init_with(s, revive_hash({}, node), node)
408
+ init_with(s, revive_hash({}, node, true), node)
373
409
  end
374
410
 
375
411
  def init_with o, h, node
@@ -378,11 +414,6 @@ module Psych
378
414
 
379
415
  if o.respond_to?(:init_with)
380
416
  o.init_with c
381
- elsif o.respond_to?(:yaml_initialize)
382
- if $VERBOSE
383
- warn "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\""
384
- end
385
- o.yaml_initialize c.tag, c.map
386
417
  else
387
418
  h.each { |k,v| o.instance_variable_set(:"@#{k}", v) }
388
419
  end
@@ -397,7 +428,7 @@ module Psych
397
428
 
398
429
  class NoAliasRuby < ToRuby
399
430
  def visit_Psych_Nodes_Alias o
400
- raise BadAlias, "Unknown alias: #{o.anchor}"
431
+ raise AliasesNotEnabled
401
432
  end
402
433
  end
403
434
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Psych
2
3
  module Visitors
3
4
  class Visitor
@@ -7,12 +8,26 @@ module Psych
7
8
 
8
9
  private
9
10
 
10
- DISPATCH = Hash.new do |hash, klass|
11
- hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
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
12
27
  end
13
28
 
14
29
  def visit target
15
- send DISPATCH[target.class], target
30
+ send dispatch[target.class], target
16
31
  end
17
32
  end
18
33
  end