psych 1.3.4 → 2.0.0

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 (88) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +138 -0
  3. data/Manifest.txt +27 -8
  4. data/README.rdoc +23 -2
  5. data/Rakefile +1 -1
  6. data/ext/psych/depend +3 -0
  7. data/ext/psych/extconf.rb +27 -11
  8. data/ext/psych/psych.h +4 -4
  9. data/ext/psych/{emitter.c → psych_emitter.c} +0 -0
  10. data/ext/psych/{emitter.h → psych_emitter.h} +0 -0
  11. data/ext/psych/{parser.c → psych_parser.c} +1 -1
  12. data/ext/psych/{parser.h → psych_parser.h} +0 -0
  13. data/ext/psych/{to_ruby.c → psych_to_ruby.c} +3 -1
  14. data/ext/psych/{to_ruby.h → psych_to_ruby.h} +0 -0
  15. data/ext/psych/{yaml_tree.c → psych_yaml_tree.c} +0 -0
  16. data/ext/psych/{yaml_tree.h → psych_yaml_tree.h} +0 -0
  17. data/ext/psych/yaml/LICENSE +19 -0
  18. data/ext/psych/yaml/api.c +1392 -0
  19. data/ext/psych/yaml/config.h +11 -0
  20. data/ext/psych/yaml/dumper.c +394 -0
  21. data/ext/psych/yaml/emitter.c +2329 -0
  22. data/ext/psych/yaml/loader.c +432 -0
  23. data/ext/psych/yaml/parser.c +1374 -0
  24. data/ext/psych/yaml/reader.c +465 -0
  25. data/ext/psych/yaml/scanner.c +3570 -0
  26. data/ext/psych/yaml/writer.c +141 -0
  27. data/ext/psych/yaml/yaml.h +1971 -0
  28. data/ext/psych/yaml/yaml_private.h +643 -0
  29. data/lib/psych.rb +217 -51
  30. data/lib/psych/class_loader.rb +101 -0
  31. data/lib/psych/core_ext.rb +1 -8
  32. data/lib/psych/deprecated.rb +3 -1
  33. data/lib/psych/exception.rb +13 -0
  34. data/lib/psych/handler.rb +13 -0
  35. data/lib/psych/handlers/recorder.rb +39 -0
  36. data/lib/psych/json/stream.rb +1 -0
  37. data/lib/psych/nodes/node.rb +3 -1
  38. data/lib/psych/scalar_scanner.rb +46 -25
  39. data/lib/psych/stream.rb +1 -0
  40. data/lib/psych/streaming.rb +10 -5
  41. data/lib/psych/syntax_error.rb +3 -1
  42. data/lib/psych/visitors/json_tree.rb +5 -2
  43. data/lib/psych/visitors/to_ruby.rb +123 -75
  44. data/lib/psych/visitors/yaml_tree.rb +59 -17
  45. data/lib/psych/y.rb +9 -0
  46. data/test/psych/handlers/test_recorder.rb +25 -0
  47. data/test/psych/helper.rb +30 -1
  48. data/test/psych/test_alias_and_anchor.rb +1 -1
  49. data/test/psych/test_array.rb +1 -1
  50. data/test/psych/test_boolean.rb +1 -1
  51. data/test/psych/test_class.rb +1 -1
  52. data/test/psych/test_coder.rb +3 -3
  53. data/test/psych/test_date_time.rb +1 -1
  54. data/test/psych/test_deprecated.rb +6 -2
  55. data/test/psych/test_document.rb +1 -1
  56. data/test/psych/test_emitter.rb +1 -1
  57. data/test/psych/test_encoding.rb +51 -65
  58. data/test/psych/test_engine_manager.rb +1 -11
  59. data/test/psych/test_exception.rb +40 -19
  60. data/test/psych/test_hash.rb +1 -1
  61. data/test/psych/test_json_tree.rb +1 -1
  62. data/test/psych/test_merge_keys.rb +52 -1
  63. data/test/psych/test_nil.rb +1 -1
  64. data/test/psych/test_null.rb +1 -1
  65. data/test/psych/test_numeric.rb +21 -1
  66. data/test/psych/test_object.rb +1 -1
  67. data/test/psych/test_object_references.rb +3 -3
  68. data/test/psych/test_omap.rb +1 -1
  69. data/test/psych/test_parser.rb +1 -1
  70. data/test/psych/test_psych.rb +15 -15
  71. data/test/psych/test_safe_load.rb +97 -0
  72. data/test/psych/test_scalar.rb +1 -1
  73. data/test/psych/test_scalar_scanner.rb +17 -2
  74. data/test/psych/test_serialize_subclasses.rb +1 -1
  75. data/test/psych/test_set.rb +1 -1
  76. data/test/psych/test_stream.rb +1 -1
  77. data/test/psych/test_string.rb +51 -3
  78. data/test/psych/test_struct.rb +1 -1
  79. data/test/psych/test_symbol.rb +1 -1
  80. data/test/psych/test_tainted.rb +8 -8
  81. data/test/psych/test_to_yaml_properties.rb +1 -1
  82. data/test/psych/test_tree_builder.rb +1 -1
  83. data/test/psych/test_yaml.rb +22 -2
  84. data/test/psych/test_yamldbm.rb +1 -1
  85. data/test/psych/test_yamlstore.rb +1 -1
  86. data/test/psych/visitors/test_to_ruby.rb +5 -4
  87. data/test/psych/visitors/test_yaml_tree.rb +19 -1
  88. metadata +45 -34
@@ -1,3 +1,7 @@
1
+ require 'psych/tree_builder'
2
+ require 'psych/scalar_scanner'
3
+ require 'psych/class_loader'
4
+
1
5
  module Psych
2
6
  module Visitors
3
7
  ###
@@ -8,16 +12,47 @@ module Psych
8
12
  # builder.tree # => #<Psych::Nodes::Stream .. }
9
13
  #
10
14
  class YAMLTree < Psych::Visitors::Visitor
15
+ class Registrar # :nodoc:
16
+ def initialize
17
+ @obj_to_id = {}
18
+ @obj_to_node = {}
19
+ @counter = 0
20
+ end
21
+
22
+ def register target, node
23
+ @obj_to_node[target.object_id] = node
24
+ end
25
+
26
+ def key? target
27
+ @obj_to_node.key? target.object_id
28
+ end
29
+
30
+ def id_for target
31
+ @obj_to_id[target.object_id] ||= (@counter += 1)
32
+ end
33
+
34
+ def node_for target
35
+ @obj_to_node[target.object_id]
36
+ end
37
+ end
38
+
11
39
  attr_reader :started, :finished
12
40
  alias :finished? :finished
13
41
  alias :started? :started
14
42
 
15
- def initialize options = {}, emitter = TreeBuilder.new, ss = ScalarScanner.new
43
+ def self.create options = {}, emitter = nil
44
+ emitter ||= TreeBuilder.new
45
+ class_loader = ClassLoader.new
46
+ ss = ScalarScanner.new class_loader
47
+ new(emitter, ss, options)
48
+ end
49
+
50
+ def initialize emitter, ss, options
16
51
  super()
17
52
  @started = false
18
53
  @finished = false
19
54
  @emitter = emitter
20
- @st = {}
55
+ @st = Registrar.new
21
56
  @ss = ss
22
57
  @options = options
23
58
  @coders = []
@@ -47,6 +82,7 @@ module Psych
47
82
 
48
83
  def tree
49
84
  finish unless finished?
85
+ @emitter.root
50
86
  end
51
87
 
52
88
  def push object
@@ -65,15 +101,15 @@ module Psych
65
101
 
66
102
  @emitter.start_document version, [], false
67
103
  accept object
68
- @emitter.end_document
104
+ @emitter.end_document !@emitter.streaming?
69
105
  end
70
106
  alias :<< :push
71
107
 
72
108
  def accept target
73
109
  # return any aliases we find
74
- if @st.key? target.object_id
75
- oid = target.object_id
76
- node = @st[oid]
110
+ if @st.key? target
111
+ oid = @st.id_for target
112
+ node = @st.node_for target
77
113
  anchor = oid.to_s
78
114
  node.anchor = anchor
79
115
  return @emitter.alias anchor
@@ -220,27 +256,33 @@ module Psych
220
256
  end
221
257
 
222
258
  def binary? string
223
- string.encoding == Encoding::ASCII_8BIT ||
259
+ (string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?) ||
224
260
  string.index("\x00") ||
225
- string.count("\x00-\x7F", "^ -~\t\r\n").fdiv(string.length) > 0.3
261
+ string.count("\x00-\x7F", "^ -~\t\r\n").fdiv(string.length) > 0.3 ||
262
+ string.class != String
226
263
  end
227
264
  private :binary?
228
265
 
229
266
  def visit_String o
230
- plain = false
231
- quote = false
232
- style = Nodes::Scalar::ANY
267
+ plain = true
268
+ quote = true
269
+ style = Nodes::Scalar::PLAIN
270
+ tag = nil
271
+ str = o
233
272
 
234
273
  if binary?(o)
235
274
  str = [o].pack('m').chomp
236
275
  tag = '!binary' # FIXME: change to below when syck is removed
237
276
  #tag = 'tag:yaml.org,2002:binary'
238
277
  style = Nodes::Scalar::LITERAL
278
+ plain = false
279
+ quote = false
280
+ elsif o =~ /\n/
281
+ style = Nodes::Scalar::LITERAL
239
282
  else
240
- str = o
241
- tag = nil
242
- quote = !(String === @ss.tokenize(o))
243
- plain = !quote
283
+ unless String === @ss.tokenize(o)
284
+ style = Nodes::Scalar::SINGLE_QUOTED
285
+ end
244
286
  end
245
287
 
246
288
  ivars = find_ivars o
@@ -402,7 +444,7 @@ module Psych
402
444
  end
403
445
 
404
446
  def register target, yaml_obj
405
- @st[target.object_id] = yaml_obj
447
+ @st.register target, yaml_obj
406
448
  yaml_obj
407
449
  end
408
450
 
@@ -432,7 +474,7 @@ module Psych
432
474
  when :map
433
475
  @emitter.start_mapping nil, c.tag, c.implicit, c.style
434
476
  c.map.each do |k,v|
435
- @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
477
+ accept k
436
478
  accept v
437
479
  end
438
480
  @emitter.end_mapping
@@ -0,0 +1,9 @@
1
+ module Kernel
2
+ ###
3
+ # An alias for Psych.dump_stream meant to be used with IRB.
4
+ def y *objects
5
+ puts Psych.dump_stream(*objects)
6
+ end
7
+ private :y
8
+ end
9
+
@@ -0,0 +1,25 @@
1
+ require 'psych/helper'
2
+ require 'psych/handlers/recorder'
3
+
4
+ module Psych
5
+ module Handlers
6
+ class TestRecorder < TestCase
7
+ def test_replay
8
+ yaml = "--- foo\n...\n"
9
+ output = StringIO.new
10
+
11
+ recorder = Psych::Handlers::Recorder.new
12
+ parser = Psych::Parser.new recorder
13
+ parser.parse yaml
14
+
15
+ assert_equal 5, recorder.events.length
16
+
17
+ emitter = Psych::Emitter.new output
18
+ recorder.events.each do |m, args|
19
+ emitter.send m, *args
20
+ end
21
+ assert_equal yaml, output.string
22
+ end
23
+ end
24
+ end
25
+ end
@@ -6,6 +6,35 @@ require 'psych'
6
6
 
7
7
  module Psych
8
8
  class TestCase < MiniTest::Unit::TestCase
9
+ def self.suppress_warning
10
+ verbose, $VERBOSE = $VERBOSE, nil
11
+ yield
12
+ ensure
13
+ $VERBOSE = verbose
14
+ end
15
+
16
+ def with_default_external(enc)
17
+ verbose, $VERBOSE = $VERBOSE, nil
18
+ origenc, Encoding.default_external = Encoding.default_external, enc
19
+ $VERBOSE = verbose
20
+ yield
21
+ ensure
22
+ verbose, $VERBOSE = $VERBOSE, nil
23
+ Encoding.default_external = origenc
24
+ $VERBOSE = verbose
25
+ end
26
+
27
+ def with_default_internal(enc)
28
+ verbose, $VERBOSE = $VERBOSE, nil
29
+ origenc, Encoding.default_internal = Encoding.default_internal, enc
30
+ $VERBOSE = verbose
31
+ yield
32
+ ensure
33
+ verbose, $VERBOSE = $VERBOSE, nil
34
+ Encoding.default_internal = origenc
35
+ $VERBOSE = verbose
36
+ end
37
+
9
38
  #
10
39
  # Convert between Psych and the object to verify correct parsing and
11
40
  # emitting
@@ -31,7 +60,7 @@ module Psych
31
60
  end
32
61
 
33
62
  def assert_cycle( obj )
34
- v = Visitors::YAMLTree.new
63
+ v = Visitors::YAMLTree.create
35
64
  v << obj
36
65
  assert_equal(obj, Psych.load(v.tree.yaml))
37
66
  assert_equal( obj, Psych::load(Psych.dump(obj)))
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  class ObjectWithInstanceVariables
4
4
  attr_accessor :var1, :var2
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  class TestArray < TestCase
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  ###
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  class TestClass < TestCase
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  class TestCoder < TestCase
@@ -85,7 +85,7 @@ module Psych
85
85
  end
86
86
 
87
87
  def encode_with coder
88
- coder.represent_map self.class.name, { 'a' => 'b' }
88
+ coder.represent_map self.class.name, { "string" => 'a', :symbol => 'b' }
89
89
  end
90
90
  end
91
91
 
@@ -131,7 +131,7 @@ module Psych
131
131
 
132
132
  def test_represent_map
133
133
  thing = Psych.load(Psych.dump(RepresentWithMap.new))
134
- assert_equal({ 'a' => 'b' }, thing.map)
134
+ assert_equal({ "string" => 'a', :symbol => 'b' }, thing.map)
135
135
  end
136
136
 
137
137
  def test_represent_sequence
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
  require 'date'
3
3
 
4
4
  module Psych
@@ -1,8 +1,9 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  class TestDeprecated < TestCase
5
5
  def teardown
6
+ $VERBOSE = @orig_verbose
6
7
  Psych.domain_types.clear
7
8
  end
8
9
 
@@ -27,6 +28,7 @@ module Psych
27
28
 
28
29
  def setup
29
30
  @qe = QuickEmitter.new
31
+ @orig_verbose, $VERBOSE = $VERBOSE, false
30
32
  end
31
33
 
32
34
  def test_quick_emit
@@ -145,7 +147,9 @@ module Psych
145
147
  end
146
148
 
147
149
  class YamlAs
148
- psych_yaml_as 'helloworld' # this should be yaml_as but to avoid syck
150
+ TestCase.suppress_warning do
151
+ psych_yaml_as 'helloworld' # this should be yaml_as but to avoid syck
152
+ end
149
153
  end
150
154
 
151
155
  def test_yaml_as
@@ -1,4 +1,4 @@
1
- require 'psych/helper'
1
+ require_relative 'helper'
2
2
 
3
3
  module Psych
4
4
  class TestDocument < TestCase
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require 'psych/helper'
3
+ require_relative 'helper'
4
4
 
5
5
  module Psych
6
6
  class TestEmitter < TestCase
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- require 'psych/helper'
3
+ require_relative 'helper'
4
4
 
5
5
  module Psych
6
6
  class TestEncoding < TestCase
@@ -50,58 +50,54 @@ module Psych
50
50
  end
51
51
 
52
52
  def test_io_shiftjis
53
- t = Tempfile.new(['shiftjis', 'yml'], :encoding => 'SHIFT_JIS')
54
- t.write '--- こんにちは!'
55
- t.close
56
-
57
- # If the external encoding isn't utf8, utf16le, or utf16be, we cannot
58
- # process the file.
59
- File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f|
60
- assert_raises Psych::SyntaxError do
61
- Psych.load(f)
53
+ Tempfile.create(['shiftjis', 'yml'], :encoding => 'SHIFT_JIS') {|t|
54
+ t.write '--- こんにちは!'
55
+ t.close
56
+
57
+ # If the external encoding isn't utf8, utf16le, or utf16be, we cannot
58
+ # process the file.
59
+ File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f|
60
+ assert_raises Psych::SyntaxError do
61
+ Psych.load(f)
62
+ end
62
63
  end
63
- end
64
-
65
- t.close(true)
64
+ }
66
65
  end
67
66
 
68
67
  def test_io_utf16le
69
- t = Tempfile.new(['utf16le', 'yml'])
70
- t.binmode
71
- t.write '--- こんにちは!'.encode('UTF-16LE')
72
- t.close
73
-
74
- File.open(t.path, 'rb', :encoding => 'UTF-16LE') do |f|
75
- assert_equal "こんにちは!", Psych.load(f)
76
- end
68
+ Tempfile.create(['utf16le', 'yml']) {|t|
69
+ t.binmode
70
+ t.write '--- こんにちは!'.encode('UTF-16LE')
71
+ t.close
77
72
 
78
- t.close(true)
73
+ File.open(t.path, 'rb', :encoding => 'UTF-16LE') do |f|
74
+ assert_equal "こんにちは!", Psych.load(f)
75
+ end
76
+ }
79
77
  end
80
78
 
81
79
  def test_io_utf16be
82
- t = Tempfile.new(['utf16be', 'yml'])
83
- t.binmode
84
- t.write '--- こんにちは!'.encode('UTF-16BE')
85
- t.close
86
-
87
- File.open(t.path, 'rb', :encoding => 'UTF-16BE') do |f|
88
- assert_equal "こんにちは!", Psych.load(f)
89
- end
80
+ Tempfile.create(['utf16be', 'yml']) {|t|
81
+ t.binmode
82
+ t.write '--- こんにちは!'.encode('UTF-16BE')
83
+ t.close
90
84
 
91
- t.close(true)
85
+ File.open(t.path, 'rb', :encoding => 'UTF-16BE') do |f|
86
+ assert_equal "こんにちは!", Psych.load(f)
87
+ end
88
+ }
92
89
  end
93
90
 
94
91
  def test_io_utf8
95
- t = Tempfile.new(['utf8', 'yml'])
96
- t.binmode
97
- t.write '--- こんにちは!'.encode('UTF-8')
98
- t.close
92
+ Tempfile.create(['utf8', 'yml']) {|t|
93
+ t.binmode
94
+ t.write '--- こんにちは!'.encode('UTF-8')
95
+ t.close
99
96
 
100
- File.open(t.path, 'rb', :encoding => 'UTF-8') do |f|
101
- assert_equal "こんにちは!", Psych.load(f)
102
- end
103
-
104
- t.close(true)
97
+ File.open(t.path, 'rb', :encoding => 'UTF-8') do |f|
98
+ assert_equal "こんにちは!", Psych.load(f)
99
+ end
100
+ }
105
101
  end
106
102
 
107
103
  def test_emit_alias
@@ -114,19 +110,14 @@ module Psych
114
110
  end
115
111
 
116
112
  def test_to_yaml_is_valid
117
- ext_before = Encoding.default_external
118
- int_before = Encoding.default_internal
119
-
120
- Encoding.default_external = Encoding::US_ASCII
121
- Encoding.default_internal = nil
122
-
123
- s = "こんにちは!"
124
- # If no encoding is specified, use UTF-8
125
- assert_equal Encoding::UTF_8, Psych.dump(s).encoding
126
- assert_equal s, Psych.load(Psych.dump(s))
127
- ensure
128
- Encoding.default_external = ext_before
129
- Encoding.default_internal = int_before
113
+ with_default_external(Encoding::US_ASCII) do
114
+ with_default_internal(nil) do
115
+ s = "こんにちは!"
116
+ # If no encoding is specified, use UTF-8
117
+ assert_equal Encoding::UTF_8, Psych.dump(s).encoding
118
+ assert_equal s, Psych.load(Psych.dump(s))
119
+ end
120
+ end
130
121
  end
131
122
 
132
123
  def test_start_mapping
@@ -191,19 +182,14 @@ module Psych
191
182
  end
192
183
 
193
184
  def test_default_internal
194
- before = Encoding.default_internal
195
-
196
- Encoding.default_internal = 'EUC-JP'
185
+ with_default_internal(Encoding::EUC_JP) do
186
+ str = "壁に耳あり、障子に目あり"
187
+ assert_equal @utf8, str.encoding
197
188
 
198
- str = "壁に耳あり、障子に目あり"
199
- yaml = "--- #{str}"
200
- assert_equal @utf8, str.encoding
201
-
202
- @parser.parse str
203
- assert_encodings Encoding.find('EUC-JP'), @handler.strings
204
- assert_equal str, @handler.strings.first.encode('UTF-8')
205
- ensure
206
- Encoding.default_internal = before
189
+ @parser.parse str
190
+ assert_encodings Encoding::EUC_JP, @handler.strings
191
+ assert_equal str, @handler.strings.first.encode('UTF-8')
192
+ end
207
193
  end
208
194
 
209
195
  def test_scalar