psych 1.1.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 (89) hide show
  1. data/.autotest +18 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG.rdoc +3 -0
  4. data/Manifest.txt +87 -0
  5. data/README.rdoc +50 -0
  6. data/Rakefile +66 -0
  7. data/ext/psych/emitter.c +517 -0
  8. data/ext/psych/emitter.h +8 -0
  9. data/ext/psych/extconf.rb +22 -0
  10. data/ext/psych/parser.c +384 -0
  11. data/ext/psych/parser.h +6 -0
  12. data/ext/psych/psych.c +34 -0
  13. data/ext/psych/psych.h +20 -0
  14. data/ext/psych/to_ruby.c +41 -0
  15. data/ext/psych/to_ruby.h +8 -0
  16. data/ext/psych/yaml_tree.c +24 -0
  17. data/ext/psych/yaml_tree.h +8 -0
  18. data/lib/psych.rb +263 -0
  19. data/lib/psych/coder.rb +94 -0
  20. data/lib/psych/core_ext.rb +39 -0
  21. data/lib/psych/deprecated.rb +82 -0
  22. data/lib/psych/handler.rb +221 -0
  23. data/lib/psych/json.rb +6 -0
  24. data/lib/psych/json/ruby_events.rb +19 -0
  25. data/lib/psych/json/stream.rb +15 -0
  26. data/lib/psych/json/tree_builder.rb +12 -0
  27. data/lib/psych/json/yaml_events.rb +29 -0
  28. data/lib/psych/nodes.rb +77 -0
  29. data/lib/psych/nodes/alias.rb +18 -0
  30. data/lib/psych/nodes/document.rb +60 -0
  31. data/lib/psych/nodes/mapping.rb +56 -0
  32. data/lib/psych/nodes/node.rb +52 -0
  33. data/lib/psych/nodes/scalar.rb +67 -0
  34. data/lib/psych/nodes/sequence.rb +81 -0
  35. data/lib/psych/nodes/stream.rb +37 -0
  36. data/lib/psych/omap.rb +4 -0
  37. data/lib/psych/parser.rb +47 -0
  38. data/lib/psych/scalar_scanner.rb +105 -0
  39. data/lib/psych/set.rb +4 -0
  40. data/lib/psych/stream.rb +36 -0
  41. data/lib/psych/streaming.rb +22 -0
  42. data/lib/psych/tree_builder.rb +94 -0
  43. data/lib/psych/visitors.rb +6 -0
  44. data/lib/psych/visitors/depth_first.rb +26 -0
  45. data/lib/psych/visitors/emitter.rb +44 -0
  46. data/lib/psych/visitors/json_tree.rb +21 -0
  47. data/lib/psych/visitors/to_ruby.rb +267 -0
  48. data/lib/psych/visitors/visitor.rb +19 -0
  49. data/lib/psych/visitors/yaml_tree.rb +373 -0
  50. data/test/psych/helper.rb +63 -0
  51. data/test/psych/json/test_stream.rb +109 -0
  52. data/test/psych/nodes/test_enumerable.rb +43 -0
  53. data/test/psych/test_alias_and_anchor.rb +26 -0
  54. data/test/psych/test_array.rb +19 -0
  55. data/test/psych/test_boolean.rb +36 -0
  56. data/test/psych/test_class.rb +17 -0
  57. data/test/psych/test_coder.rb +184 -0
  58. data/test/psych/test_date_time.rb +17 -0
  59. data/test/psych/test_deprecated.rb +210 -0
  60. data/test/psych/test_document.rb +46 -0
  61. data/test/psych/test_emitter.rb +94 -0
  62. data/test/psych/test_encoding.rb +179 -0
  63. data/test/psych/test_engine_manager.rb +57 -0
  64. data/test/psych/test_exception.rb +39 -0
  65. data/test/psych/test_hash.rb +30 -0
  66. data/test/psych/test_json_tree.rb +65 -0
  67. data/test/psych/test_merge_keys.rb +72 -0
  68. data/test/psych/test_nil.rb +18 -0
  69. data/test/psych/test_null.rb +19 -0
  70. data/test/psych/test_object.rb +27 -0
  71. data/test/psych/test_omap.rb +68 -0
  72. data/test/psych/test_parser.rb +297 -0
  73. data/test/psych/test_psych.rb +168 -0
  74. data/test/psych/test_scalar.rb +11 -0
  75. data/test/psych/test_scalar_scanner.rb +69 -0
  76. data/test/psych/test_serialize_subclasses.rb +38 -0
  77. data/test/psych/test_set.rb +49 -0
  78. data/test/psych/test_stream.rb +49 -0
  79. data/test/psych/test_string.rb +49 -0
  80. data/test/psych/test_struct.rb +51 -0
  81. data/test/psych/test_symbol.rb +17 -0
  82. data/test/psych/test_to_yaml_properties.rb +63 -0
  83. data/test/psych/test_tree_builder.rb +79 -0
  84. data/test/psych/test_yaml.rb +1256 -0
  85. data/test/psych/visitors/test_depth_first.rb +49 -0
  86. data/test/psych/visitors/test_emitter.rb +144 -0
  87. data/test/psych/visitors/test_to_ruby.rb +325 -0
  88. data/test/psych/visitors/test_yaml_tree.rb +155 -0
  89. metadata +232 -0
@@ -0,0 +1,168 @@
1
+ require 'psych/helper'
2
+
3
+ require 'stringio'
4
+ require 'tempfile'
5
+
6
+ class TestPsych < Psych::TestCase
7
+ def teardown
8
+ Psych.domain_types.clear
9
+ end
10
+
11
+ def test_line_width
12
+ yml = Psych.dump('123456 7', { :line_width => 5 })
13
+ assert_match(/^\s*7/, yml)
14
+ end
15
+
16
+ def test_indent
17
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:indentation => 5})
18
+ assert_match(/^[ ]{5}b/, yml)
19
+ end
20
+
21
+ def test_canonical
22
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:canonical => true})
23
+ assert_match(/\? ! "b/, yml)
24
+ end
25
+
26
+ def test_header
27
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:header => true})
28
+ assert_match(/YAML/, yml)
29
+ end
30
+
31
+ def test_version_array
32
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:version => [1,1]})
33
+ assert_match(/1.1/, yml)
34
+ end
35
+
36
+ def test_version_string
37
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:version => '1.1'})
38
+ assert_match(/1.1/, yml)
39
+ end
40
+
41
+ def test_version_bool
42
+ yml = Psych.dump({:a => {'b' => 'c'}}, {:version => true})
43
+ assert_match(/1.1/, yml)
44
+ end
45
+
46
+ def test_load_argument_error
47
+ assert_raises(TypeError) do
48
+ Psych.load nil
49
+ end
50
+ end
51
+
52
+ def test_non_existing_class_on_deserialize
53
+ e = assert_raises(ArgumentError) do
54
+ Psych.load("--- !ruby/object:NonExistent\nfoo: 1")
55
+ end
56
+ assert_equal 'undefined class/module NonExistent', e.message
57
+ end
58
+
59
+ def test_dump_stream
60
+ things = [22, "foo \n", {}]
61
+ stream = Psych.dump_stream(*things)
62
+ assert_equal things, Psych.load_stream(stream)
63
+ end
64
+
65
+ def test_dump_file
66
+ hash = {'hello' => 'TGIF!'}
67
+ Tempfile.open('fun.yml') do |io|
68
+ assert_equal io, Psych.dump(hash, io)
69
+ io.rewind
70
+ assert_equal Psych.dump(hash), io.read
71
+ end
72
+ end
73
+
74
+ def test_dump_io
75
+ hash = {'hello' => 'TGIF!'}
76
+ stringio = StringIO.new ''
77
+ assert_equal stringio, Psych.dump(hash, stringio)
78
+ assert_equal Psych.dump(hash), stringio.string
79
+ end
80
+
81
+ def test_simple
82
+ assert_equal 'foo', Psych.load("--- foo\n")
83
+ end
84
+
85
+ def test_libyaml_version
86
+ assert Psych.libyaml_version
87
+ assert_equal Psych.libyaml_version.join('.'), Psych::LIBYAML_VERSION
88
+ end
89
+
90
+ def test_load_documents
91
+ docs = Psych.load_documents("--- foo\n...\n--- bar\n...")
92
+ assert_equal %w{ foo bar }, docs
93
+ end
94
+
95
+ def test_parse_stream
96
+ docs = Psych.parse_stream("--- foo\n...\n--- bar\n...")
97
+ assert_equal %w{ foo bar }, docs.children.map { |x| x.transform }
98
+ end
99
+
100
+ def test_add_builtin_type
101
+ got = nil
102
+ Psych.add_builtin_type 'omap' do |type, val|
103
+ got = val
104
+ end
105
+ Psych.load('--- !!omap hello')
106
+ assert_equal 'hello', got
107
+ ensure
108
+ Psych.remove_type 'omap'
109
+ end
110
+
111
+ def test_domain_types
112
+ got = nil
113
+ Psych.add_domain_type 'foo.bar,2002', 'foo' do |type, val|
114
+ got = val
115
+ end
116
+
117
+ Psych.load('--- !foo.bar,2002/foo hello')
118
+ assert_equal 'hello', got
119
+
120
+ Psych.load("--- !foo.bar,2002/foo\n- hello\n- world")
121
+ assert_equal %w{ hello world }, got
122
+
123
+ Psych.load("--- !foo.bar,2002/foo\nhello: world")
124
+ assert_equal({ 'hello' => 'world' }, got)
125
+ end
126
+
127
+ def test_load_file
128
+ t = Tempfile.new(['yikes', 'yml'])
129
+ t.binmode
130
+ t.write('--- hello world')
131
+ t.close
132
+ assert_equal 'hello world', Psych.load_file(t.path)
133
+ t.close(true)
134
+ end
135
+
136
+ def test_parse_file
137
+ t = Tempfile.new(['yikes', 'yml'])
138
+ t.binmode
139
+ t.write('--- hello world')
140
+ t.close
141
+ assert_equal 'hello world', Psych.parse_file(t.path).transform
142
+ t.close(true)
143
+ end
144
+
145
+ def test_degenerate_strings
146
+ assert_equal false, Psych.load(' ')
147
+ assert_equal false, Psych.parse(' ')
148
+ assert_equal false, Psych.load('')
149
+ assert_equal false, Psych.parse('')
150
+ end
151
+
152
+ def test_callbacks
153
+ types = []
154
+ appender = lambda { |*args| types << args }
155
+
156
+ Psych.add_builtin_type('foo', &appender)
157
+ Psych.add_domain_type('example.com,2002', 'foo', &appender)
158
+ Psych.load <<-eoyml
159
+ - !tag:yaml.org,2002:foo bar
160
+ - !tag:example.com,2002:foo bar
161
+ eoyml
162
+
163
+ assert_equal [
164
+ ["tag:yaml.org,2002:foo", "bar"],
165
+ ["tag:example.com,2002:foo", "bar"]
166
+ ], types
167
+ end
168
+ end
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'psych/helper'
4
+
5
+ module Psych
6
+ class TestScalar < TestCase
7
+ def test_utf_8
8
+ assert_equal "日本語", Psych.load("--- 日本語")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,69 @@
1
+ require 'psych/helper'
2
+
3
+ module Psych
4
+ class TestScalarScanner < TestCase
5
+ attr_reader :ss
6
+
7
+ def setup
8
+ super
9
+ @ss = Psych::ScalarScanner.new
10
+ end
11
+
12
+ def test_scan_time
13
+ { '2001-12-15T02:59:43.1Z' => Time.utc(2001, 12, 15, 02, 59, 43, 100000),
14
+ '2001-12-14t21:59:43.10-05:00' => Time.utc(2001, 12, 15, 02, 59, 43, 100000),
15
+ '2001-12-14 21:59:43.10 -5' => Time.utc(2001, 12, 15, 02, 59, 43, 100000),
16
+ '2001-12-15 2:59:43.10' => Time.utc(2001, 12, 15, 02, 59, 43, 100000),
17
+ '2011-02-24 11:17:06 -0800' => Time.utc(2011, 02, 24, 19, 17, 06)
18
+ }.each do |time_str, time|
19
+ assert_equal time, @ss.tokenize(time_str)
20
+ end
21
+ end
22
+
23
+ def test_scan_date
24
+ date = '1980-12-16'
25
+ token = @ss.tokenize date
26
+ assert_equal 1980, token.year
27
+ assert_equal 12, token.month
28
+ assert_equal 16, token.day
29
+ end
30
+
31
+ def test_scan_inf
32
+ assert_equal(1 / 0.0, ss.tokenize('.inf'))
33
+ end
34
+
35
+ def test_scan_minus_inf
36
+ assert_equal(-1 / 0.0, ss.tokenize('-.inf'))
37
+ end
38
+
39
+ def test_scan_nan
40
+ assert ss.tokenize('.nan').nan?
41
+ end
42
+
43
+ def test_scan_null
44
+ assert_equal nil, ss.tokenize('null')
45
+ assert_equal nil, ss.tokenize('~')
46
+ assert_equal nil, ss.tokenize('')
47
+ end
48
+
49
+ def test_scan_symbol
50
+ assert_equal :foo, ss.tokenize(':foo')
51
+ end
52
+
53
+ def test_scan_sexagesimal_float
54
+ assert_equal 685230.15, ss.tokenize('190:20:30.15')
55
+ end
56
+
57
+ def test_scan_sexagesimal_int
58
+ assert_equal 685230, ss.tokenize('190:20:30')
59
+ end
60
+
61
+ def test_scan_float
62
+ assert_equal 1.2, ss.tokenize('1.2')
63
+ end
64
+
65
+ def test_scan_true
66
+ assert_equal true, ss.tokenize('true')
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,38 @@
1
+ require 'psych/helper'
2
+
3
+ module Psych
4
+ class TestSerializeSubclasses < TestCase
5
+ class SomeObject
6
+ def initialize one, two
7
+ @one = one
8
+ @two = two
9
+ end
10
+
11
+ def == other
12
+ @one == other.instance_eval { @one } &&
13
+ @two == other.instance_eval { @two }
14
+ end
15
+ end
16
+
17
+ def test_some_object
18
+ so = SomeObject.new('foo', [1,2,3])
19
+ assert_equal so, Psych.load(Psych.dump(so))
20
+ end
21
+
22
+ class StructSubclass < Struct.new(:foo)
23
+ def initialize foo, bar
24
+ super(foo)
25
+ @bar = bar
26
+ end
27
+
28
+ def == other
29
+ super(other) && @bar == other.instance_eval{ @bar }
30
+ end
31
+ end
32
+
33
+ def test_struct_subclass
34
+ so = StructSubclass.new('foo', [1,2,3])
35
+ assert_equal so, Psych.load(Psych.dump(so))
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,49 @@
1
+ require 'psych/helper'
2
+
3
+ module Psych
4
+ class TestSet < TestCase
5
+ def setup
6
+ super
7
+ @set = Psych::Set.new
8
+ @set['foo'] = 'bar'
9
+ @set['bar'] = 'baz'
10
+ end
11
+
12
+ def test_dump
13
+ assert_match(/!set/, Psych.dump(@set))
14
+ end
15
+
16
+ def test_roundtrip
17
+ assert_cycle(@set)
18
+ end
19
+
20
+ ###
21
+ # FIXME: Syck should also support !!set as shorthand
22
+ def test_load_from_yaml
23
+ loaded = Psych.load(<<-eoyml)
24
+ --- !set
25
+ foo: bar
26
+ bar: baz
27
+ eoyml
28
+ assert_equal(@set, loaded)
29
+ end
30
+
31
+ def test_loaded_class
32
+ assert_instance_of(Psych::Set, Psych.load(Psych.dump(@set)))
33
+ end
34
+
35
+ def test_set_shorthand
36
+ loaded = Psych.load(<<-eoyml)
37
+ --- !!set
38
+ foo: bar
39
+ bar: baz
40
+ eoyml
41
+ assert_instance_of(Psych::Set, loaded)
42
+ end
43
+
44
+ def test_set_self_reference
45
+ @set['self'] = @set
46
+ assert_cycle(@set)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ require 'psych/helper'
2
+
3
+ module Psych
4
+ class TestStream < TestCase
5
+ def test_explicit_documents
6
+ io = StringIO.new
7
+ stream = Psych::Stream.new(io)
8
+ stream.start
9
+ stream.push({ 'foo' => 'bar' })
10
+
11
+ assert !stream.finished?, 'stream not finished'
12
+ stream.finish
13
+ assert stream.finished?, 'stream finished'
14
+
15
+ assert_match(/^---/, io.string)
16
+ assert_match(/\.\.\.$/, io.string)
17
+ end
18
+
19
+ def test_start_takes_block
20
+ io = StringIO.new
21
+ stream = Psych::Stream.new(io)
22
+ stream.start do |emitter|
23
+ emitter.push({ 'foo' => 'bar' })
24
+ end
25
+
26
+ assert stream.finished?, 'stream finished'
27
+ assert_match(/^---/, io.string)
28
+ assert_match(/\.\.\.$/, io.string)
29
+ end
30
+
31
+ def test_no_backreferences
32
+ io = StringIO.new
33
+ stream = Psych::Stream.new(io)
34
+ stream.start do |emitter|
35
+ x = { 'foo' => 'bar' }
36
+ emitter.push x
37
+ emitter.push x
38
+ end
39
+
40
+ assert stream.finished?, 'stream finished'
41
+ assert_match(/^---/, io.string)
42
+ assert_match(/\.\.\.$/, io.string)
43
+ assert_equal 2, io.string.scan('---').length
44
+ assert_equal 2, io.string.scan('...').length
45
+ assert_equal 2, io.string.scan('foo').length
46
+ assert_equal 2, io.string.scan('bar').length
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ require 'psych/helper'
2
+
3
+ module Psych
4
+ class TestString < TestCase
5
+ def test_binary_string_null
6
+ string = "\x00"
7
+ yml = Psych.dump string
8
+ assert_match(/binary/, yml)
9
+ assert_equal string, Psych.load(yml)
10
+ end
11
+
12
+ def test_binary_string
13
+ string = binary_string
14
+ yml = Psych.dump string
15
+ assert_match(/binary/, yml)
16
+ assert_equal string, Psych.load(yml)
17
+ end
18
+
19
+ def test_non_binary_string
20
+ string = binary_string(0.29)
21
+ yml = Psych.dump string
22
+ refute_match(/binary/, yml)
23
+ assert_equal string, Psych.load(yml)
24
+ end
25
+
26
+ def test_string_with_ivars
27
+ food = "is delicious"
28
+ ivar = "on rock and roll"
29
+ food.instance_variable_set(:@we_built_this_city, ivar)
30
+
31
+ str = Psych.load Psych.dump food
32
+ assert_equal ivar, food.instance_variable_get(:@we_built_this_city)
33
+ end
34
+
35
+ def test_binary
36
+ string = [0, 123,22, 44, 9, 32, 34, 39].pack('C*')
37
+ assert_cycle string
38
+ end
39
+
40
+ def binary_string percentage = 0.31, length = 100
41
+ string = ''
42
+ (percentage * length).to_i.times do |i|
43
+ string << "\b"
44
+ end
45
+ string << 'a' * (length - string.length)
46
+ string
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,51 @@
1
+ require 'psych/helper'
2
+
3
+ class PsychStructWithIvar < Struct.new(:foo)
4
+ attr_reader :bar
5
+ def initialize *args
6
+ super
7
+ @bar = 'hello'
8
+ end
9
+ end
10
+
11
+ module Psych
12
+ class TestStruct < TestCase
13
+ class StructSubclass < Struct.new(:foo)
14
+ def initialize foo, bar
15
+ super(foo)
16
+ @bar = bar
17
+ end
18
+ end
19
+
20
+ def test_self_referential_struct
21
+ ss = StructSubclass.new(nil, 'foo')
22
+ ss.foo = ss
23
+
24
+ loaded = Psych.load(Psych.dump(ss))
25
+ assert_instance_of(StructSubclass, loaded.foo)
26
+
27
+ # FIXME: This seems to cause an infinite loop. wtf. Must report a bug
28
+ # in ruby.
29
+ # assert_equal(ss, loaded)
30
+ end
31
+
32
+ def test_roundtrip
33
+ thing = PsychStructWithIvar.new('bar')
34
+ struct = Psych.load(Psych.dump(thing))
35
+
36
+ assert_equal 'hello', struct.bar
37
+ assert_equal 'bar', struct.foo
38
+ end
39
+
40
+ def test_load
41
+ obj = Psych.load(<<-eoyml)
42
+ --- !ruby/struct:PsychStructWithIvar
43
+ :foo: bar
44
+ :@bar: hello
45
+ eoyml
46
+
47
+ assert_equal 'hello', obj.bar
48
+ assert_equal 'bar', obj.foo
49
+ end
50
+ end
51
+ end