psych 1.3.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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