psych 2.2.1 → 5.1.2

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 (70) 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 +13 -13
  5. data/ext/psych/depend +14 -0
  6. data/ext/psych/extconf.rb +43 -29
  7. data/ext/psych/psych.c +6 -3
  8. data/ext/psych/psych_emitter.c +10 -9
  9. data/ext/psych/psych_parser.c +69 -72
  10. data/ext/psych/psych_yaml_tree.c +0 -12
  11. data/lib/psych/class_loader.rb +11 -9
  12. data/lib/psych/coder.rb +1 -1
  13. data/lib/psych/core_ext.rb +3 -20
  14. data/lib/psych/exception.rb +17 -3
  15. data/lib/psych/handler.rb +8 -3
  16. data/lib/psych/handlers/document_stream.rb +2 -2
  17. data/lib/psych/handlers/recorder.rb +2 -2
  18. data/lib/psych/json/ruby_events.rb +1 -1
  19. data/lib/psych/json/stream.rb +3 -3
  20. data/lib/psych/json/tree_builder.rb +2 -2
  21. data/lib/psych/json/yaml_events.rb +1 -1
  22. data/lib/psych/nodes/alias.rb +3 -1
  23. data/lib/psych/nodes/document.rb +3 -1
  24. data/lib/psych/nodes/mapping.rb +3 -1
  25. data/lib/psych/nodes/node.rb +24 -5
  26. data/lib/psych/nodes/scalar.rb +4 -2
  27. data/lib/psych/nodes/sequence.rb +3 -1
  28. data/lib/psych/nodes/stream.rb +3 -1
  29. data/lib/psych/nodes.rb +8 -8
  30. data/lib/psych/omap.rb +1 -1
  31. data/lib/psych/parser.rb +14 -1
  32. data/lib/psych/scalar_scanner.rb +39 -47
  33. data/lib/psych/set.rb +1 -1
  34. data/lib/psych/stream.rb +1 -1
  35. data/lib/psych/streaming.rb +1 -1
  36. data/lib/psych/syntax_error.rb +2 -2
  37. data/lib/psych/tree_builder.rb +48 -8
  38. data/lib/psych/versions.rb +5 -4
  39. data/lib/psych/visitors/depth_first.rb +1 -1
  40. data/lib/psych/visitors/emitter.rb +1 -1
  41. data/lib/psych/visitors/json_tree.rb +2 -2
  42. data/lib/psych/visitors/to_ruby.rb +61 -31
  43. data/lib/psych/visitors/visitor.rb +18 -4
  44. data/lib/psych/visitors/yaml_tree.rb +111 -123
  45. data/lib/psych/visitors.rb +7 -7
  46. data/lib/psych/y.rb +1 -1
  47. data/lib/psych.rb +333 -96
  48. metadata +16 -52
  49. data/.gitignore +0 -14
  50. data/.travis.yml +0 -18
  51. data/CHANGELOG.rdoc +0 -576
  52. data/Gemfile +0 -3
  53. data/Mavenfile +0 -7
  54. data/Rakefile +0 -33
  55. data/bin/console +0 -7
  56. data/bin/setup +0 -6
  57. data/ext/psych/.gitignore +0 -11
  58. data/ext/psych/yaml/api.c +0 -1392
  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 -444
  63. data/ext/psych/yaml/parser.c +0 -1374
  64. data/ext/psych/yaml/reader.c +0 -469
  65. data/ext/psych/yaml/scanner.c +0 -3576
  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 -662
  69. data/lib/psych/deprecated.rb +0 -86
  70. data/psych.gemspec +0 -43
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: false
2
- require 'psych/handler'
1
+ # frozen_string_literal: true
2
+ require_relative 'handler'
3
3
 
4
4
  module Psych
5
5
  ###
@@ -23,23 +23,38 @@ module Psych
23
23
  @stack = []
24
24
  @last = nil
25
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
26
38
  end
27
39
 
28
40
  %w{
29
41
  Sequence
30
42
  Mapping
31
43
  }.each do |node|
32
- class_eval %{
44
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
33
45
  def start_#{node.downcase}(anchor, tag, implicit, style)
34
46
  n = Nodes::#{node}.new(anchor, tag, implicit, style)
47
+ set_start_location(n)
35
48
  @last.children << n
36
49
  push n
37
50
  end
38
51
 
39
52
  def end_#{node.downcase}
40
- pop
53
+ n = pop
54
+ set_end_location(n)
55
+ n
41
56
  end
42
- }
57
+ RUBY
43
58
  end
44
59
 
45
60
  ###
@@ -49,6 +64,7 @@ module Psych
49
64
  # See Psych::Handler#start_document
50
65
  def start_document version, tag_directives, implicit
51
66
  n = Nodes::Document.new version, tag_directives, implicit
67
+ set_start_location(n)
52
68
  @last.children << n
53
69
  push n
54
70
  end
@@ -60,26 +76,35 @@ module Psych
60
76
  # See Psych::Handler#start_document
61
77
  def end_document implicit_end = !streaming?
62
78
  @last.implicit_end = implicit_end
63
- pop
79
+ n = pop
80
+ set_end_location(n)
81
+ n
64
82
  end
65
83
 
66
84
  def start_stream encoding
67
85
  @root = Nodes::Stream.new(encoding)
86
+ set_start_location(@root)
68
87
  push @root
69
88
  end
70
89
 
71
90
  def end_stream
72
- pop
91
+ n = pop
92
+ set_end_location(n)
93
+ n
73
94
  end
74
95
 
75
96
  def scalar value, anchor, tag, plain, quoted, style
76
97
  s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
98
+ set_location(s)
77
99
  @last.children << s
78
100
  s
79
101
  end
80
102
 
81
103
  def alias anchor
82
- @last.children << Nodes::Alias.new(anchor)
104
+ a = Nodes::Alias.new(anchor)
105
+ set_location(a)
106
+ @last.children << a
107
+ a
83
108
  end
84
109
 
85
110
  private
@@ -93,5 +118,20 @@ module Psych
93
118
  @last = @stack.last
94
119
  x
95
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
96
136
  end
97
137
  end
@@ -1,9 +1,10 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
+
2
3
  module Psych
3
- # The version is Psych you're using
4
- VERSION = '2.2.1'
4
+ # The version of Psych you are using
5
+ VERSION = '5.1.2'
5
6
 
6
7
  if RUBY_ENGINE == 'jruby'
7
- DEFAULT_SNAKEYAML_VERSION = '1.17'.freeze
8
+ DEFAULT_SNAKEYAML_VERSION = '2.7'.freeze
8
9
  end
9
10
  end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  module Psych
3
3
  module Visitors
4
4
  class DepthFirst < Psych::Visitors::Visitor
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  module Psych
3
3
  module Visitors
4
4
  class Emitter < Psych::Visitors::Visitor
@@ -1,5 +1,5 @@
1
- # frozen_string_literal: false
2
- require 'psych/json/ruby_events'
1
+ # frozen_string_literal: true
2
+ require_relative '../json/ruby_events'
3
3
 
4
4
  module Psych
5
5
  module Visitors
@@ -1,7 +1,7 @@
1
- # frozen_string_literal: false
2
- require 'psych/scalar_scanner'
3
- require 'psych/class_loader'
4
- require 'psych/exception'
1
+ # frozen_string_literal: true
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
- key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
36
- 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 =~ /^(?:tag:|x-private)/
37
40
 
38
- if @domain_types.key? key
39
- value, block = @domain_types[key]
40
- 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
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(Psych.load_tags[o.tag])
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).to_datetime
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"
@@ -94,7 +101,7 @@ module Psych
94
101
  source = $1
95
102
  options = 0
96
103
  lang = nil
97
- ($2 || '').split('').each do |option|
104
+ $2&.each_char do |option|
98
105
  case option
99
106
  when 'x' then options |= Regexp::EXTENDED
100
107
  when 'i' then options |= Regexp::IGNORECASE
@@ -124,7 +131,7 @@ module Psych
124
131
  end
125
132
 
126
133
  def visit_Psych_Nodes_Sequence o
127
- if klass = resolve_class(Psych.load_tags[o.tag])
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 Psych.load_tags[o.tag]
160
- return revive(resolve_class(Psych.load_tags[o.tag]), o)
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'
@@ -316,10 +325,11 @@ module Psych
316
325
  end
317
326
 
318
327
  def visit_Psych_Nodes_Alias o
319
- @st.fetch(o.anchor) { raise BadAlias, "Unknown alias: #{o.anchor}" }
328
+ @st.fetch(o.anchor) { raise AnchorNotDefined, o.anchor }
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
- SHOVEL = '<<'
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 == SHOVEL && k.tag != "tag:yaml.org,2002:str"
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
@@ -380,11 +415,6 @@ module Psych
380
415
 
381
416
  if o.respond_to?(:init_with)
382
417
  o.init_with c
383
- elsif o.respond_to?(:yaml_initialize)
384
- if $VERBOSE
385
- warn "Implementing #{o.class}#yaml_initialize is deprecated, please implement \"init_with(coder)\""
386
- end
387
- o.yaml_initialize c.tag, c.map
388
418
  else
389
419
  h.each { |k,v| o.instance_variable_set(:"@#{k}", v) }
390
420
  end
@@ -399,7 +429,7 @@ module Psych
399
429
 
400
430
  class NoAliasRuby < ToRuby
401
431
  def visit_Psych_Nodes_Alias o
402
- raise BadAlias, "Unknown alias: #{o.anchor}"
432
+ raise AliasesNotEnabled
403
433
  end
404
434
  end
405
435
  end
@@ -1,4 +1,4 @@
1
- # frozen_string_literal: false
1
+ # frozen_string_literal: true
2
2
  module Psych
3
3
  module Visitors
4
4
  class Visitor
@@ -8,12 +8,26 @@ module Psych
8
8
 
9
9
  private
10
10
 
11
- DISPATCH = Hash.new do |hash, klass|
12
- 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
13
27
  end
14
28
 
15
29
  def visit target
16
- send DISPATCH[target.class], target
30
+ send dispatch[target.class], target
17
31
  end
18
32
  end
19
33
  end