psych 1.2.2 → 1.3.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.
- data/.travis.yml +6 -0
- data/CHANGELOG.rdoc +126 -0
- data/Manifest.txt +3 -2
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/ext/psych/emitter.c +1 -1
- data/ext/psych/parser.c +241 -62
- data/lib/psych.rb +86 -21
- data/lib/psych/core_ext.rb +2 -0
- data/lib/psych/handlers/document_stream.rb +22 -0
- data/lib/psych/parser.rb +4 -0
- data/lib/psych/scalar_scanner.rb +15 -5
- data/lib/psych/syntax_error.rb +19 -0
- data/lib/psych/tree_builder.rb +3 -1
- data/lib/psych/visitors/to_ruby.rb +51 -15
- data/lib/psych/visitors/yaml_tree.rb +58 -11
- data/test/psych/test_array.rb +28 -0
- data/test/psych/test_encoding.rb +73 -0
- data/test/psych/test_exception.rb +91 -0
- data/test/psych/test_numeric.rb +11 -0
- data/test/psych/test_object_references.rb +67 -0
- data/test/psych/test_parser.rb +44 -9
- data/test/psych/test_scalar_scanner.rb +22 -0
- data/test/psych/test_stream.rb +44 -0
- data/test/psych/test_string.rb +31 -0
- data/test/psych/test_struct.rb +1 -3
- data/test/psych/test_tainted.rb +3 -1
- data/test/psych/test_yamldbm.rb +16 -9
- data/test/psych/test_yamlstore.rb +6 -6
- metadata +57 -68
- data/Gemfile +0 -11
- data/lib/psych/json.rb +0 -6
data/lib/psych.rb
CHANGED
@@ -10,7 +10,10 @@ require 'psych/set'
|
|
10
10
|
require 'psych/coder'
|
11
11
|
require 'psych/core_ext'
|
12
12
|
require 'psych/deprecated'
|
13
|
-
require 'psych/
|
13
|
+
require 'psych/stream'
|
14
|
+
require 'psych/json/tree_builder'
|
15
|
+
require 'psych/json/stream'
|
16
|
+
require 'psych/handlers/document_stream'
|
14
17
|
|
15
18
|
###
|
16
19
|
# = Overview
|
@@ -90,7 +93,7 @@ require 'psych/json'
|
|
90
93
|
|
91
94
|
module Psych
|
92
95
|
# The version is Psych you're using
|
93
|
-
VERSION = '1.
|
96
|
+
VERSION = '1.3.0'
|
94
97
|
|
95
98
|
# The version of libyaml Psych is using
|
96
99
|
LIBYAML_VERSION = Psych.libyaml_version.join '.'
|
@@ -101,39 +104,63 @@ module Psych
|
|
101
104
|
class BadAlias < Exception
|
102
105
|
end
|
103
106
|
|
104
|
-
autoload :Stream, 'psych/stream'
|
105
|
-
|
106
107
|
###
|
107
108
|
# Load +yaml+ in to a Ruby data structure. If multiple documents are
|
108
109
|
# provided, the object contained in the first document will be returned.
|
110
|
+
# +filename+ will be used in the exception message if any exception is raised
|
111
|
+
# while parsing.
|
112
|
+
#
|
113
|
+
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
109
114
|
#
|
110
115
|
# Example:
|
111
116
|
#
|
112
|
-
# Psych.load("--- a")
|
113
|
-
# Psych.load("---\n - a\n - b")
|
114
|
-
|
115
|
-
|
117
|
+
# Psych.load("--- a") # => 'a'
|
118
|
+
# Psych.load("---\n - a\n - b") # => ['a', 'b']
|
119
|
+
#
|
120
|
+
# begin
|
121
|
+
# Psych.load("--- `", "file.txt")
|
122
|
+
# rescue Psych::SyntaxError => ex
|
123
|
+
# ex.file # => 'file.txt'
|
124
|
+
# ex.message # => "(foo.txt): found character that cannot start any token"
|
125
|
+
# end
|
126
|
+
def self.load yaml, filename = nil
|
127
|
+
result = parse(yaml, filename)
|
116
128
|
result ? result.to_ruby : result
|
117
129
|
end
|
118
130
|
|
119
131
|
###
|
120
132
|
# Parse a YAML string in +yaml+. Returns the first object of a YAML AST.
|
133
|
+
# +filename+ is used in the exception message if a Psych::SyntaxError is
|
134
|
+
# raised.
|
135
|
+
#
|
136
|
+
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
121
137
|
#
|
122
138
|
# Example:
|
123
139
|
#
|
124
140
|
# Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Sequence:0x00>
|
125
141
|
#
|
142
|
+
# begin
|
143
|
+
# Psych.parse("--- `", "file.txt")
|
144
|
+
# rescue Psych::SyntaxError => ex
|
145
|
+
# ex.file # => 'file.txt'
|
146
|
+
# ex.message # => "(foo.txt): found character that cannot start any token"
|
147
|
+
# end
|
148
|
+
#
|
126
149
|
# See Psych::Nodes for more information about YAML AST.
|
127
|
-
def self.parse yaml
|
128
|
-
|
129
|
-
|
150
|
+
def self.parse yaml, filename = nil
|
151
|
+
parse_stream(yaml, filename) do |node|
|
152
|
+
return node
|
153
|
+
end
|
154
|
+
false
|
130
155
|
end
|
131
156
|
|
132
157
|
###
|
133
158
|
# Parse a file at +filename+. Returns the YAML AST.
|
159
|
+
#
|
160
|
+
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
134
161
|
def self.parse_file filename
|
135
|
-
File.open filename do |f|
|
136
|
-
parse f
|
162
|
+
File.open filename, 'r:bom|utf-8' do |f|
|
163
|
+
parse f, filename
|
137
164
|
end
|
138
165
|
end
|
139
166
|
|
@@ -146,16 +173,39 @@ module Psych
|
|
146
173
|
###
|
147
174
|
# Parse a YAML string in +yaml+. Returns the full AST for the YAML document.
|
148
175
|
# This method can handle multiple YAML documents contained in +yaml+.
|
176
|
+
# +filename+ is used in the exception message if a Psych::SyntaxError is
|
177
|
+
# raised.
|
178
|
+
#
|
179
|
+
# If a block is given, a Psych::Nodes::Document node will be yielded to the
|
180
|
+
# block as it's being parsed.
|
181
|
+
#
|
182
|
+
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
|
149
183
|
#
|
150
184
|
# Example:
|
151
185
|
#
|
152
186
|
# Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
|
153
187
|
#
|
188
|
+
# Psych.parse_stream("--- a\n--- b") do |node|
|
189
|
+
# node # => #<Psych::Nodes::Document:0x00>
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# begin
|
193
|
+
# Psych.parse_stream("--- `", "file.txt")
|
194
|
+
# rescue Psych::SyntaxError => ex
|
195
|
+
# ex.file # => 'file.txt'
|
196
|
+
# ex.message # => "(foo.txt): found character that cannot start any token"
|
197
|
+
# end
|
198
|
+
#
|
154
199
|
# See Psych::Nodes for more information about YAML AST.
|
155
|
-
def self.parse_stream yaml
|
156
|
-
|
157
|
-
|
158
|
-
|
200
|
+
def self.parse_stream yaml, filename = nil, &block
|
201
|
+
if block_given?
|
202
|
+
parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
|
203
|
+
parser.parse yaml, filename
|
204
|
+
else
|
205
|
+
parser = self.parser
|
206
|
+
parser.parse yaml, filename
|
207
|
+
parser.handler.root
|
208
|
+
end
|
159
209
|
end
|
160
210
|
|
161
211
|
###
|
@@ -217,19 +267,34 @@ module Psych
|
|
217
267
|
|
218
268
|
###
|
219
269
|
# Load multiple documents given in +yaml+. Returns the parsed documents
|
220
|
-
# as a list.
|
270
|
+
# as a list. If a block is given, each document will be converted to ruby
|
271
|
+
# and passed to the block during parsing
|
272
|
+
#
|
273
|
+
# Example:
|
221
274
|
#
|
222
275
|
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
|
223
276
|
#
|
224
|
-
|
225
|
-
|
277
|
+
# list = []
|
278
|
+
# Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
|
279
|
+
# list << ruby
|
280
|
+
# end
|
281
|
+
# list # => ['foo', 'bar']
|
282
|
+
#
|
283
|
+
def self.load_stream yaml, filename = nil
|
284
|
+
if block_given?
|
285
|
+
parse_stream(yaml, filename) do |node|
|
286
|
+
yield node.to_ruby
|
287
|
+
end
|
288
|
+
else
|
289
|
+
parse_stream(yaml, filename).children.map { |child| child.to_ruby }
|
290
|
+
end
|
226
291
|
end
|
227
292
|
|
228
293
|
###
|
229
294
|
# Load the document contained in +filename+. Returns the yaml contained in
|
230
295
|
# +filename+ as a ruby object
|
231
296
|
def self.load_file filename
|
232
|
-
|
297
|
+
File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename }
|
233
298
|
end
|
234
299
|
|
235
300
|
# :stopdoc:
|
data/lib/psych/core_ext.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'psych/tree_builder'
|
2
|
+
|
3
|
+
module Psych
|
4
|
+
module Handlers
|
5
|
+
class DocumentStream < Psych::TreeBuilder # :nodoc:
|
6
|
+
def initialize &block
|
7
|
+
super
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def start_document version, tag_directives, implicit
|
12
|
+
n = Nodes::Document.new version, tag_directives, implicit
|
13
|
+
push n
|
14
|
+
end
|
15
|
+
|
16
|
+
def end_document implicit_end = !streaming?
|
17
|
+
@last.implicit_end = implicit_end
|
18
|
+
@block.call pop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/psych/parser.rb
CHANGED
@@ -36,12 +36,16 @@ module Psych
|
|
36
36
|
# The handler on which events will be called
|
37
37
|
attr_accessor :handler
|
38
38
|
|
39
|
+
# Set the encoding for this parser to +encoding+
|
40
|
+
attr_writer :external_encoding
|
41
|
+
|
39
42
|
###
|
40
43
|
# Creates a new Psych::Parser instance with +handler+. YAML events will
|
41
44
|
# be called on +handler+. See Psych::Parser for more details.
|
42
45
|
|
43
46
|
def initialize handler = Handler.new
|
44
47
|
@handler = handler
|
48
|
+
@external_encoding = ANY
|
45
49
|
end
|
46
50
|
end
|
47
51
|
end
|
data/lib/psych/scalar_scanner.rb
CHANGED
@@ -46,9 +46,13 @@ module Psych
|
|
46
46
|
end
|
47
47
|
when TIME
|
48
48
|
parse_time string
|
49
|
-
when /^\d{4}
|
49
|
+
when /^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/
|
50
50
|
require 'date'
|
51
|
-
|
51
|
+
begin
|
52
|
+
Date.strptime(string, '%Y-%m-%d')
|
53
|
+
rescue ArgumentError
|
54
|
+
string
|
55
|
+
end
|
52
56
|
when /^\.inf$/i
|
53
57
|
1 / 0.0
|
54
58
|
when /^-\.inf$/i
|
@@ -61,7 +65,7 @@ module Psych
|
|
61
65
|
else
|
62
66
|
string.sub(/^:/, '').to_sym
|
63
67
|
end
|
64
|
-
when /^[-+]?[
|
68
|
+
when /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
|
65
69
|
i = 0
|
66
70
|
string.split(':').each_with_index do |n,e|
|
67
71
|
i += (n.to_i * 60 ** (e - 2).abs)
|
@@ -74,13 +78,19 @@ module Psych
|
|
74
78
|
end
|
75
79
|
i
|
76
80
|
when FLOAT
|
77
|
-
|
81
|
+
begin
|
82
|
+
return Float(string.gsub(/[,_]/, ''))
|
83
|
+
rescue ArgumentError
|
84
|
+
end
|
78
85
|
|
79
86
|
@string_cache[string] = true
|
80
87
|
string
|
81
88
|
else
|
82
89
|
if string.count('.') < 2
|
83
|
-
|
90
|
+
begin
|
91
|
+
return Integer(string.gsub(/[,_]/, ''))
|
92
|
+
rescue ArgumentError
|
93
|
+
end
|
84
94
|
end
|
85
95
|
|
86
96
|
@string_cache[string] = true
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Psych
|
2
|
+
class SyntaxError < ::SyntaxError
|
3
|
+
attr_reader :file, :line, :column, :offset, :problem, :context
|
4
|
+
|
5
|
+
def initialize file, line, col, offset, problem, context
|
6
|
+
err = [problem, context].compact.join ' '
|
7
|
+
filename = file || '<unknown>'
|
8
|
+
message = "(%s): %s at line %d column %d" % [filename, err, line, col]
|
9
|
+
|
10
|
+
@file = file
|
11
|
+
@line = line
|
12
|
+
@column = col
|
13
|
+
@offset = offset
|
14
|
+
@problem = problem
|
15
|
+
@context = context
|
16
|
+
super(message)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/psych/tree_builder.rb
CHANGED
@@ -72,7 +72,9 @@ module Psych
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def scalar value, anchor, tag, plain, quoted, style
|
75
|
-
|
75
|
+
s = Nodes::Scalar.new(value,anchor,tag,plain,quoted,style)
|
76
|
+
@last.children << s
|
77
|
+
s
|
76
78
|
end
|
77
79
|
|
78
80
|
def alias anchor
|
@@ -31,9 +31,7 @@ module Psych
|
|
31
31
|
result
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
@st[o.anchor] = o.value if o.anchor
|
36
|
-
|
34
|
+
def deserialize o
|
37
35
|
if klass = Psych.load_tags[o.tag]
|
38
36
|
instance = klass.allocate
|
39
37
|
|
@@ -52,8 +50,16 @@ module Psych
|
|
52
50
|
case o.tag
|
53
51
|
when '!binary', 'tag:yaml.org,2002:binary'
|
54
52
|
o.value.unpack('m').first
|
55
|
-
when
|
56
|
-
|
53
|
+
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
54
|
+
klass = resolve_class($1)
|
55
|
+
if klass
|
56
|
+
klass.allocate.replace o.value
|
57
|
+
else
|
58
|
+
o.value
|
59
|
+
end
|
60
|
+
when '!ruby/object:BigDecimal'
|
61
|
+
require 'bigdecimal'
|
62
|
+
BigDecimal._load o.value
|
57
63
|
when "!ruby/object:DateTime"
|
58
64
|
require 'date'
|
59
65
|
@ss.parse_time(o.value).to_datetime
|
@@ -92,6 +98,11 @@ module Psych
|
|
92
98
|
@ss.tokenize o.value
|
93
99
|
end
|
94
100
|
end
|
101
|
+
private :deserialize
|
102
|
+
|
103
|
+
def visit_Psych_Nodes_Scalar o
|
104
|
+
register o, deserialize(o)
|
105
|
+
end
|
95
106
|
|
96
107
|
def visit_Psych_Nodes_Sequence o
|
97
108
|
if klass = Psych.load_tags[o.tag]
|
@@ -108,15 +119,18 @@ module Psych
|
|
108
119
|
|
109
120
|
case o.tag
|
110
121
|
when '!omap', 'tag:yaml.org,2002:omap'
|
111
|
-
map = Psych::Omap.new
|
112
|
-
@st[o.anchor] = map if o.anchor
|
122
|
+
map = register(o, Psych::Omap.new)
|
113
123
|
o.children.each { |a|
|
114
124
|
map[accept(a.children.first)] = accept a.children.last
|
115
125
|
}
|
116
126
|
map
|
127
|
+
when /^!(?:seq|ruby\/array):(.*)$/
|
128
|
+
klass = resolve_class($1)
|
129
|
+
list = register(o, klass.allocate)
|
130
|
+
o.children.each { |c| list.push accept c }
|
131
|
+
list
|
117
132
|
else
|
118
|
-
list = []
|
119
|
-
@st[o.anchor] = list if o.anchor
|
133
|
+
list = register(o, [])
|
120
134
|
o.children.each { |c| list.push accept c }
|
121
135
|
list
|
122
136
|
end
|
@@ -127,16 +141,33 @@ module Psych
|
|
127
141
|
return revive_hash({}, o) unless o.tag
|
128
142
|
|
129
143
|
case o.tag
|
130
|
-
when
|
144
|
+
when /^!(?:str|ruby\/string)(?::(.*))?/, 'tag:yaml.org,2002:str'
|
145
|
+
klass = resolve_class($1)
|
131
146
|
members = Hash[*o.children.map { |c| accept c }]
|
132
147
|
string = members.delete 'str'
|
148
|
+
|
149
|
+
if klass
|
150
|
+
string = klass.allocate
|
151
|
+
string.replace string
|
152
|
+
end
|
153
|
+
|
133
154
|
init_with(string, members.map { |k,v| [k.to_s.sub(/^@/, ''),v] }, o)
|
155
|
+
when /^!ruby\/array:(.*)$/
|
156
|
+
klass = resolve_class($1)
|
157
|
+
list = register(o, klass.allocate)
|
158
|
+
|
159
|
+
members = Hash[o.children.map { |c| accept c }.each_slice(2).to_a]
|
160
|
+
list.replace members['internal']
|
161
|
+
|
162
|
+
members['ivars'].each do |ivar, v|
|
163
|
+
list.instance_variable_set ivar, v
|
164
|
+
end
|
165
|
+
list
|
134
166
|
when /^!ruby\/struct:?(.*)?$/
|
135
167
|
klass = resolve_class($1)
|
136
168
|
|
137
169
|
if klass
|
138
|
-
s = klass.allocate
|
139
|
-
@st[o.anchor] = s if o.anchor
|
170
|
+
s = register(o, klass.allocate)
|
140
171
|
|
141
172
|
members = {}
|
142
173
|
struct_members = s.members.map { |x| x.to_sym }
|
@@ -158,7 +189,7 @@ module Psych
|
|
158
189
|
|
159
190
|
when '!ruby/range'
|
160
191
|
h = Hash[*o.children.map { |c| accept c }]
|
161
|
-
Range.new(h['begin'], h['end'], h['excl'])
|
192
|
+
register o, Range.new(h['begin'], h['end'], h['excl'])
|
162
193
|
|
163
194
|
when /^!ruby\/exception:?(.*)?$/
|
164
195
|
h = Hash[*o.children.map { |c| accept c }]
|
@@ -177,11 +208,11 @@ module Psych
|
|
177
208
|
|
178
209
|
when '!ruby/object:Complex'
|
179
210
|
h = Hash[*o.children.map { |c| accept c }]
|
180
|
-
Complex(h['real'], h['image'])
|
211
|
+
register o, Complex(h['real'], h['image'])
|
181
212
|
|
182
213
|
when '!ruby/object:Rational'
|
183
214
|
h = Hash[*o.children.map { |c| accept c }]
|
184
|
-
Rational(h['numerator'], h['denominator'])
|
215
|
+
register o, Rational(h['numerator'], h['denominator'])
|
185
216
|
|
186
217
|
when /^!ruby\/object:?(.*)?$/
|
187
218
|
name = $1 || 'Object'
|
@@ -209,6 +240,11 @@ module Psych
|
|
209
240
|
end
|
210
241
|
|
211
242
|
private
|
243
|
+
def register node, object
|
244
|
+
@st[node.anchor] = object if node.anchor
|
245
|
+
object
|
246
|
+
end
|
247
|
+
|
212
248
|
def revive_hash hash, o
|
213
249
|
@st[o.anchor] = hash if o.anchor
|
214
250
|
|
@@ -159,13 +159,13 @@ module Psych
|
|
159
159
|
end
|
160
160
|
|
161
161
|
def visit_Regexp o
|
162
|
-
@emitter.scalar
|
162
|
+
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
|
163
163
|
end
|
164
164
|
|
165
165
|
def visit_DateTime o
|
166
166
|
formatted = format_time o.to_time
|
167
167
|
tag = '!ruby/object:DateTime'
|
168
|
-
@emitter.scalar
|
168
|
+
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
|
169
169
|
end
|
170
170
|
|
171
171
|
def visit_Time o
|
@@ -174,7 +174,7 @@ module Psych
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def visit_Rational o
|
177
|
-
@emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
|
177
|
+
register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
|
178
178
|
|
179
179
|
[
|
180
180
|
'denominator', o.denominator.to_s,
|
@@ -187,7 +187,7 @@ module Psych
|
|
187
187
|
end
|
188
188
|
|
189
189
|
def visit_Complex o
|
190
|
-
@emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
|
190
|
+
register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
|
191
191
|
|
192
192
|
['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
|
193
193
|
@emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
|
@@ -214,6 +214,10 @@ module Psych
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
+
def visit_BigDecimal o
|
218
|
+
@emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
|
219
|
+
end
|
220
|
+
|
217
221
|
def binary? string
|
218
222
|
string.encoding == Encoding::ASCII_8BIT ||
|
219
223
|
string.index("\x00") ||
|
@@ -241,9 +245,15 @@ module Psych
|
|
241
245
|
ivars = find_ivars o
|
242
246
|
|
243
247
|
if ivars.empty?
|
248
|
+
unless o.class == ::String
|
249
|
+
tag = "!ruby/string:#{o.class}"
|
250
|
+
end
|
244
251
|
@emitter.scalar str, nil, tag, plain, quote, style
|
245
252
|
else
|
246
|
-
|
253
|
+
maptag = '!ruby/string'
|
254
|
+
maptag << ":#{o.class}" unless o.class == ::String
|
255
|
+
|
256
|
+
@emitter.start_mapping nil, maptag, false, Nodes::Mapping::BLOCK
|
247
257
|
@emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
|
248
258
|
@emitter.scalar str, nil, tag, plain, quote, style
|
249
259
|
|
@@ -255,16 +265,16 @@ module Psych
|
|
255
265
|
|
256
266
|
def visit_Module o
|
257
267
|
raise TypeError, "can't dump anonymous module: #{o}" unless o.name
|
258
|
-
@emitter.scalar
|
268
|
+
register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
|
259
269
|
end
|
260
270
|
|
261
271
|
def visit_Class o
|
262
272
|
raise TypeError, "can't dump anonymous class: #{o}" unless o.name
|
263
|
-
@emitter.scalar
|
273
|
+
register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
|
264
274
|
end
|
265
275
|
|
266
276
|
def visit_Range o
|
267
|
-
@emitter.start_mapping
|
277
|
+
register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
|
268
278
|
['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
|
269
279
|
accept m
|
270
280
|
end
|
@@ -297,9 +307,13 @@ module Psych
|
|
297
307
|
end
|
298
308
|
|
299
309
|
def visit_Array o
|
300
|
-
|
301
|
-
|
302
|
-
|
310
|
+
if o.class == ::Array
|
311
|
+
register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
312
|
+
o.each { |c| accept c }
|
313
|
+
@emitter.end_sequence
|
314
|
+
else
|
315
|
+
visit_array_subclass o
|
316
|
+
end
|
303
317
|
end
|
304
318
|
|
305
319
|
def visit_NilClass o
|
@@ -311,6 +325,39 @@ module Psych
|
|
311
325
|
end
|
312
326
|
|
313
327
|
private
|
328
|
+
def visit_array_subclass o
|
329
|
+
tag = "!ruby/array:#{o.class}"
|
330
|
+
if o.instance_variables.empty?
|
331
|
+
node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
|
332
|
+
register o, node
|
333
|
+
o.each { |c| accept c }
|
334
|
+
@emitter.end_sequence
|
335
|
+
else
|
336
|
+
node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
|
337
|
+
register o, node
|
338
|
+
|
339
|
+
# Dump the internal list
|
340
|
+
accept 'internal'
|
341
|
+
@emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
|
342
|
+
o.each { |c| accept c }
|
343
|
+
@emitter.end_sequence
|
344
|
+
|
345
|
+
# Dump the ivars
|
346
|
+
accept 'ivars'
|
347
|
+
@emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
|
348
|
+
o.instance_variables.each do |ivar|
|
349
|
+
accept ivar
|
350
|
+
accept o.instance_variable_get ivar
|
351
|
+
end
|
352
|
+
@emitter.end_mapping
|
353
|
+
|
354
|
+
@emitter.end_mapping
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def dump_list o
|
359
|
+
end
|
360
|
+
|
314
361
|
# '%:z' was no defined until 1.9.3
|
315
362
|
if RUBY_VERSION < '1.9.3'
|
316
363
|
def format_time time
|