psych 3.0.0.beta2-x64-mingw32

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 (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +20 -0
  4. data/CHANGELOG.rdoc +576 -0
  5. data/Gemfile +3 -0
  6. data/Mavenfile +7 -0
  7. data/README.md +73 -0
  8. data/Rakefile +46 -0
  9. data/bin/console +7 -0
  10. data/bin/setup +6 -0
  11. data/ext/psych/.gitignore +11 -0
  12. data/ext/psych/depend +3 -0
  13. data/ext/psych/extconf.rb +39 -0
  14. data/ext/psych/psych.c +34 -0
  15. data/ext/psych/psych.h +17 -0
  16. data/ext/psych/psych_emitter.c +554 -0
  17. data/ext/psych/psych_emitter.h +8 -0
  18. data/ext/psych/psych_parser.c +568 -0
  19. data/ext/psych/psych_parser.h +6 -0
  20. data/ext/psych/psych_to_ruby.c +39 -0
  21. data/ext/psych/psych_to_ruby.h +8 -0
  22. data/ext/psych/psych_yaml_tree.c +24 -0
  23. data/ext/psych/psych_yaml_tree.h +8 -0
  24. data/ext/psych/yaml/LICENSE +19 -0
  25. data/ext/psych/yaml/api.c +1392 -0
  26. data/ext/psych/yaml/config.h +10 -0
  27. data/ext/psych/yaml/dumper.c +394 -0
  28. data/ext/psych/yaml/emitter.c +2329 -0
  29. data/ext/psych/yaml/loader.c +444 -0
  30. data/ext/psych/yaml/parser.c +1374 -0
  31. data/ext/psych/yaml/reader.c +469 -0
  32. data/ext/psych/yaml/scanner.c +3576 -0
  33. data/ext/psych/yaml/writer.c +141 -0
  34. data/ext/psych/yaml/yaml.h +1971 -0
  35. data/ext/psych/yaml/yaml_private.h +662 -0
  36. data/lib/psych.rb +511 -0
  37. data/lib/psych/class_loader.rb +102 -0
  38. data/lib/psych/coder.rb +95 -0
  39. data/lib/psych/core_ext.rb +19 -0
  40. data/lib/psych/exception.rb +14 -0
  41. data/lib/psych/handler.rb +250 -0
  42. data/lib/psych/handlers/document_stream.rb +23 -0
  43. data/lib/psych/handlers/recorder.rb +40 -0
  44. data/lib/psych/json/ruby_events.rb +20 -0
  45. data/lib/psych/json/stream.rb +17 -0
  46. data/lib/psych/json/tree_builder.rb +13 -0
  47. data/lib/psych/json/yaml_events.rb +30 -0
  48. data/lib/psych/nodes.rb +78 -0
  49. data/lib/psych/nodes/alias.rb +19 -0
  50. data/lib/psych/nodes/document.rb +61 -0
  51. data/lib/psych/nodes/mapping.rb +57 -0
  52. data/lib/psych/nodes/node.rb +56 -0
  53. data/lib/psych/nodes/scalar.rb +68 -0
  54. data/lib/psych/nodes/sequence.rb +82 -0
  55. data/lib/psych/nodes/stream.rb +38 -0
  56. data/lib/psych/omap.rb +5 -0
  57. data/lib/psych/parser.rb +52 -0
  58. data/lib/psych/scalar_scanner.rb +149 -0
  59. data/lib/psych/set.rb +5 -0
  60. data/lib/psych/stream.rb +38 -0
  61. data/lib/psych/streaming.rb +28 -0
  62. data/lib/psych/syntax_error.rb +22 -0
  63. data/lib/psych/tree_builder.rb +97 -0
  64. data/lib/psych/versions.rb +9 -0
  65. data/lib/psych/visitors.rb +7 -0
  66. data/lib/psych/visitors/depth_first.rb +27 -0
  67. data/lib/psych/visitors/emitter.rb +52 -0
  68. data/lib/psych/visitors/json_tree.rb +25 -0
  69. data/lib/psych/visitors/to_ruby.rb +401 -0
  70. data/lib/psych/visitors/visitor.rb +20 -0
  71. data/lib/psych/visitors/yaml_tree.rb +551 -0
  72. data/lib/psych/y.rb +10 -0
  73. data/psych.gemspec +64 -0
  74. metadata +175 -0
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Psych
3
+ module Visitors
4
+ class Visitor
5
+ def accept target
6
+ visit target
7
+ end
8
+
9
+ private
10
+
11
+ DISPATCH = Hash.new do |hash, klass|
12
+ hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
13
+ end
14
+
15
+ def visit target
16
+ send DISPATCH[target.class], target
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,551 @@
1
+ # frozen_string_literal: true
2
+ require 'psych/tree_builder'
3
+ require 'psych/scalar_scanner'
4
+ require 'psych/class_loader'
5
+
6
+ module Psych
7
+ module Visitors
8
+ ###
9
+ # YAMLTree builds a YAML ast given a Ruby object. For example:
10
+ #
11
+ # builder = Psych::Visitors::YAMLTree.new
12
+ # builder << { :foo => 'bar' }
13
+ # builder.tree # => #<Psych::Nodes::Stream .. }
14
+ #
15
+ class YAMLTree < Psych::Visitors::Visitor
16
+ class Registrar # :nodoc:
17
+ def initialize
18
+ @obj_to_id = {}
19
+ @obj_to_node = {}
20
+ @targets = []
21
+ @counter = 0
22
+ end
23
+
24
+ def register target, node
25
+ return unless target.respond_to? :object_id
26
+ @targets << target
27
+ @obj_to_node[target.object_id] = node
28
+ end
29
+
30
+ def key? target
31
+ @obj_to_node.key? target.object_id
32
+ rescue NoMethodError
33
+ false
34
+ end
35
+
36
+ def id_for target
37
+ @obj_to_id[target.object_id] ||= (@counter += 1)
38
+ end
39
+
40
+ def node_for target
41
+ @obj_to_node[target.object_id]
42
+ end
43
+ end
44
+
45
+ attr_reader :started, :finished
46
+ alias :finished? :finished
47
+ alias :started? :started
48
+
49
+ def self.create options = {}, emitter = nil
50
+ emitter ||= TreeBuilder.new
51
+ class_loader = ClassLoader.new
52
+ ss = ScalarScanner.new class_loader
53
+ new(emitter, ss, options)
54
+ end
55
+
56
+ def initialize emitter, ss, options
57
+ super()
58
+ @started = false
59
+ @finished = false
60
+ @emitter = emitter
61
+ @st = Registrar.new
62
+ @ss = ss
63
+ @options = options
64
+ @line_width = options[:line_width]
65
+ if @line_width && @line_width < 0
66
+ if @line_width == -1
67
+ # Treat -1 as unlimited line-width, same as libyaml does.
68
+ @line_width = nil
69
+ else
70
+ fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.")
71
+ end
72
+ end
73
+ @coders = []
74
+
75
+ @dispatch_cache = Hash.new do |h,klass|
76
+ method = "visit_#{(klass.name || '').split('::').join('_')}"
77
+
78
+ method = respond_to?(method) ? method : h[klass.superclass]
79
+
80
+ raise(TypeError, "Can't dump #{target.class}") unless method
81
+
82
+ h[klass] = method
83
+ end
84
+ end
85
+
86
+ def start encoding = Nodes::Stream::UTF8
87
+ @emitter.start_stream(encoding).tap do
88
+ @started = true
89
+ end
90
+ end
91
+
92
+ def finish
93
+ @emitter.end_stream.tap do
94
+ @finished = true
95
+ end
96
+ end
97
+
98
+ def tree
99
+ finish unless finished?
100
+ @emitter.root
101
+ end
102
+
103
+ def push object
104
+ start unless started?
105
+ version = []
106
+ version = [1,1] if @options[:header]
107
+
108
+ case @options[:version]
109
+ when Array
110
+ version = @options[:version]
111
+ when String
112
+ version = @options[:version].split('.').map { |x| x.to_i }
113
+ else
114
+ version = [1,1]
115
+ end if @options.key? :version
116
+
117
+ @emitter.start_document version, [], false
118
+ accept object
119
+ @emitter.end_document !@emitter.streaming?
120
+ end
121
+ alias :<< :push
122
+
123
+ def accept target
124
+ # return any aliases we find
125
+ if @st.key? target
126
+ oid = @st.id_for target
127
+ node = @st.node_for target
128
+ anchor = oid.to_s
129
+ node.anchor = anchor
130
+ return @emitter.alias anchor
131
+ end
132
+
133
+ if target.respond_to?(:encode_with)
134
+ dump_coder target
135
+ else
136
+ send(@dispatch_cache[target.class], target)
137
+ end
138
+ end
139
+
140
+ def visit_Psych_Omap o
141
+ seq = @emitter.start_sequence(nil, 'tag:yaml.org,2002:omap', false, Nodes::Sequence::BLOCK)
142
+ register(o, seq)
143
+
144
+ o.each { |k,v| visit_Hash k => v }
145
+ @emitter.end_sequence
146
+ end
147
+
148
+ def visit_Encoding o
149
+ tag = "!ruby/encoding"
150
+ @emitter.scalar o.name, nil, tag, false, false, Nodes::Scalar::ANY
151
+ end
152
+
153
+ def visit_Object o
154
+ tag = Psych.dump_tags[o.class]
155
+ unless tag
156
+ klass = o.class == Object ? nil : o.class.name
157
+ tag = ['!ruby/object', klass].compact.join(':')
158
+ end
159
+
160
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
161
+ register(o, map)
162
+
163
+ dump_ivars o
164
+ @emitter.end_mapping
165
+ end
166
+
167
+ alias :visit_Delegator :visit_Object
168
+
169
+ def visit_Struct o
170
+ tag = ['!ruby/struct', o.class.name].compact.join(':')
171
+
172
+ register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
173
+ o.members.each do |member|
174
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
175
+ accept o[member]
176
+ end
177
+
178
+ dump_ivars o
179
+
180
+ @emitter.end_mapping
181
+ end
182
+
183
+ def visit_Exception o
184
+ tag = ['!ruby/exception', o.class.name].join ':'
185
+
186
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
187
+
188
+ {
189
+ 'message' => private_iv_get(o, 'mesg'),
190
+ 'backtrace' => private_iv_get(o, 'backtrace'),
191
+ }.each do |k,v|
192
+ next unless v
193
+ @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
194
+ accept v
195
+ end
196
+
197
+ dump_ivars o
198
+
199
+ @emitter.end_mapping
200
+ end
201
+
202
+ def visit_NameError o
203
+ tag = ['!ruby/exception', o.class.name].join ':'
204
+
205
+ @emitter.start_mapping nil, tag, false, Nodes::Mapping::BLOCK
206
+
207
+ {
208
+ 'message' => o.message.to_s,
209
+ 'backtrace' => private_iv_get(o, 'backtrace'),
210
+ }.each do |k,v|
211
+ next unless v
212
+ @emitter.scalar k, nil, nil, true, false, Nodes::Scalar::ANY
213
+ accept v
214
+ end
215
+
216
+ dump_ivars o
217
+
218
+ @emitter.end_mapping
219
+ end
220
+
221
+ def visit_Regexp o
222
+ register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
223
+ end
224
+
225
+ def visit_DateTime o
226
+ formatted = if o.offset.zero?
227
+ o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
228
+ else
229
+ o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
230
+ end
231
+ tag = '!ruby/object:DateTime'
232
+ register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
233
+ end
234
+
235
+ def visit_Time o
236
+ formatted = format_time o
237
+ register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
238
+ end
239
+
240
+ def visit_Rational o
241
+ register o, @emitter.start_mapping(nil, '!ruby/object:Rational', false, Nodes::Mapping::BLOCK)
242
+
243
+ [
244
+ 'denominator', o.denominator.to_s,
245
+ 'numerator', o.numerator.to_s
246
+ ].each do |m|
247
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
248
+ end
249
+
250
+ @emitter.end_mapping
251
+ end
252
+
253
+ def visit_Complex o
254
+ register o, @emitter.start_mapping(nil, '!ruby/object:Complex', false, Nodes::Mapping::BLOCK)
255
+
256
+ ['real', o.real.to_s, 'image', o.imag.to_s].each do |m|
257
+ @emitter.scalar m, nil, nil, true, false, Nodes::Scalar::ANY
258
+ end
259
+
260
+ @emitter.end_mapping
261
+ end
262
+
263
+ def visit_Integer o
264
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
265
+ end
266
+ alias :visit_TrueClass :visit_Integer
267
+ alias :visit_FalseClass :visit_Integer
268
+ alias :visit_Date :visit_Integer
269
+
270
+ def visit_Float o
271
+ if o.nan?
272
+ @emitter.scalar '.nan', nil, nil, true, false, Nodes::Scalar::ANY
273
+ elsif o.infinite?
274
+ @emitter.scalar((o.infinite? > 0 ? '.inf' : '-.inf'),
275
+ nil, nil, true, false, Nodes::Scalar::ANY)
276
+ else
277
+ @emitter.scalar o.to_s, nil, nil, true, false, Nodes::Scalar::ANY
278
+ end
279
+ end
280
+
281
+ def visit_BigDecimal o
282
+ @emitter.scalar o._dump, nil, '!ruby/object:BigDecimal', false, false, Nodes::Scalar::ANY
283
+ end
284
+
285
+ def visit_String o
286
+ plain = true
287
+ quote = true
288
+ style = Nodes::Scalar::PLAIN
289
+ tag = nil
290
+
291
+ if binary?(o)
292
+ o = [o].pack('m0')
293
+ tag = '!binary' # FIXME: change to below when syck is removed
294
+ #tag = 'tag:yaml.org,2002:binary'
295
+ style = Nodes::Scalar::LITERAL
296
+ plain = false
297
+ quote = false
298
+ elsif o =~ /\n(?!\Z)/ # match \n except blank line at the end of string
299
+ style = Nodes::Scalar::LITERAL
300
+ elsif o == '<<'
301
+ style = Nodes::Scalar::SINGLE_QUOTED
302
+ tag = 'tag:yaml.org,2002:str'
303
+ plain = false
304
+ quote = false
305
+ elsif @line_width && o.length > @line_width
306
+ style = Nodes::Scalar::FOLDED
307
+ elsif o =~ /^[^[:word:]][^"]*$/
308
+ style = Nodes::Scalar::DOUBLE_QUOTED
309
+ elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/ =~ o
310
+ style = Nodes::Scalar::SINGLE_QUOTED
311
+ end
312
+
313
+ is_primitive = o.class == ::String
314
+ ivars = is_primitive ? [] : o.instance_variables
315
+
316
+ if ivars.empty?
317
+ unless is_primitive
318
+ tag = "!ruby/string:#{o.class}"
319
+ plain = false
320
+ quote = false
321
+ end
322
+ @emitter.scalar o, nil, tag, plain, quote, style
323
+ else
324
+ maptag = '!ruby/string'.dup
325
+ maptag << ":#{o.class}" unless o.class == ::String
326
+
327
+ register o, @emitter.start_mapping(nil, maptag, false, Nodes::Mapping::BLOCK)
328
+ @emitter.scalar 'str', nil, nil, true, false, Nodes::Scalar::ANY
329
+ @emitter.scalar o, nil, tag, plain, quote, style
330
+
331
+ dump_ivars o
332
+
333
+ @emitter.end_mapping
334
+ end
335
+ end
336
+
337
+ def visit_Module o
338
+ raise TypeError, "can't dump anonymous module: #{o}" unless o.name
339
+ register o, @emitter.scalar(o.name, nil, '!ruby/module', false, false, Nodes::Scalar::SINGLE_QUOTED)
340
+ end
341
+
342
+ def visit_Class o
343
+ raise TypeError, "can't dump anonymous class: #{o}" unless o.name
344
+ register o, @emitter.scalar(o.name, nil, '!ruby/class', false, false, Nodes::Scalar::SINGLE_QUOTED)
345
+ end
346
+
347
+ def visit_Range o
348
+ register o, @emitter.start_mapping(nil, '!ruby/range', false, Nodes::Mapping::BLOCK)
349
+ ['begin', o.begin, 'end', o.end, 'excl', o.exclude_end?].each do |m|
350
+ accept m
351
+ end
352
+ @emitter.end_mapping
353
+ end
354
+
355
+ def visit_Hash o
356
+ if o.class == ::Hash
357
+ register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK))
358
+ o.each do |k,v|
359
+ accept k
360
+ accept v
361
+ end
362
+ @emitter.end_mapping
363
+ else
364
+ visit_hash_subclass o
365
+ end
366
+ end
367
+
368
+ def visit_Psych_Set o
369
+ register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK))
370
+
371
+ o.each do |k,v|
372
+ accept k
373
+ accept v
374
+ end
375
+
376
+ @emitter.end_mapping
377
+ end
378
+
379
+ def visit_Array o
380
+ if o.class == ::Array
381
+ visit_Enumerator o
382
+ else
383
+ visit_array_subclass o
384
+ end
385
+ end
386
+
387
+ def visit_Enumerator o
388
+ register o, @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
389
+ o.each { |c| accept c }
390
+ @emitter.end_sequence
391
+ end
392
+
393
+ def visit_NilClass o
394
+ @emitter.scalar('', nil, 'tag:yaml.org,2002:null', true, false, Nodes::Scalar::ANY)
395
+ end
396
+
397
+ def visit_Symbol o
398
+ if o.empty?
399
+ @emitter.scalar "", nil, '!ruby/symbol', false, false, Nodes::Scalar::ANY
400
+ else
401
+ @emitter.scalar ":#{o}", nil, nil, true, false, Nodes::Scalar::ANY
402
+ end
403
+ end
404
+
405
+ def visit_BasicObject o
406
+ tag = Psych.dump_tags[o.class]
407
+ tag ||= "!ruby/marshalable:#{o.class.name}"
408
+
409
+ map = @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
410
+ register(o, map)
411
+
412
+ o.marshal_dump.each(&method(:accept))
413
+
414
+ @emitter.end_mapping
415
+ end
416
+
417
+ private
418
+
419
+ def binary? string
420
+ string.encoding == Encoding::ASCII_8BIT && !string.ascii_only?
421
+ end
422
+
423
+ def visit_array_subclass o
424
+ tag = "!ruby/array:#{o.class}"
425
+ ivars = o.instance_variables
426
+ if ivars.empty?
427
+ node = @emitter.start_sequence(nil, tag, false, Nodes::Sequence::BLOCK)
428
+ register o, node
429
+ o.each { |c| accept c }
430
+ @emitter.end_sequence
431
+ else
432
+ node = @emitter.start_mapping(nil, tag, false, Nodes::Sequence::BLOCK)
433
+ register o, node
434
+
435
+ # Dump the internal list
436
+ accept 'internal'
437
+ @emitter.start_sequence(nil, nil, true, Nodes::Sequence::BLOCK)
438
+ o.each { |c| accept c }
439
+ @emitter.end_sequence
440
+
441
+ # Dump the ivars
442
+ accept 'ivars'
443
+ @emitter.start_mapping(nil, nil, true, Nodes::Sequence::BLOCK)
444
+ ivars.each do |ivar|
445
+ accept ivar
446
+ accept o.instance_variable_get ivar
447
+ end
448
+ @emitter.end_mapping
449
+
450
+ @emitter.end_mapping
451
+ end
452
+ end
453
+
454
+ def visit_hash_subclass o
455
+ ivars = o.instance_variables
456
+ if ivars.any?
457
+ tag = "!ruby/hash-with-ivars:#{o.class}"
458
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
459
+ register(o, node)
460
+
461
+ # Dump the elements
462
+ accept 'elements'
463
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
464
+ o.each do |k,v|
465
+ accept k
466
+ accept v
467
+ end
468
+ @emitter.end_mapping
469
+
470
+ # Dump the ivars
471
+ accept 'ivars'
472
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
473
+ o.instance_variables.each do |ivar|
474
+ accept ivar
475
+ accept o.instance_variable_get ivar
476
+ end
477
+ @emitter.end_mapping
478
+
479
+ @emitter.end_mapping
480
+ else
481
+ tag = "!ruby/hash:#{o.class}"
482
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
483
+ register(o, node)
484
+ o.each do |k,v|
485
+ accept k
486
+ accept v
487
+ end
488
+ @emitter.end_mapping
489
+ end
490
+ end
491
+
492
+ def dump_list o
493
+ end
494
+
495
+ def format_time time
496
+ if time.utc?
497
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
498
+ else
499
+ time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
500
+ end
501
+ end
502
+
503
+ def register target, yaml_obj
504
+ @st.register target, yaml_obj
505
+ yaml_obj
506
+ end
507
+
508
+ def dump_coder o
509
+ @coders << o
510
+ tag = Psych.dump_tags[o.class]
511
+ unless tag
512
+ klass = o.class == Object ? nil : o.class.name
513
+ tag = ['!ruby/object', klass].compact.join(':')
514
+ end
515
+
516
+ c = Psych::Coder.new(tag)
517
+ o.encode_with(c)
518
+ emit_coder c, o
519
+ end
520
+
521
+ def emit_coder c, o
522
+ case c.type
523
+ when :scalar
524
+ @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY
525
+ when :seq
526
+ @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK
527
+ c.seq.each do |thing|
528
+ accept thing
529
+ end
530
+ @emitter.end_sequence
531
+ when :map
532
+ register o, @emitter.start_mapping(nil, c.tag, c.implicit, c.style)
533
+ c.map.each do |k,v|
534
+ accept k
535
+ accept v
536
+ end
537
+ @emitter.end_mapping
538
+ when :object
539
+ accept c.object
540
+ end
541
+ end
542
+
543
+ def dump_ivars target
544
+ target.instance_variables.each do |iv|
545
+ @emitter.scalar("#{iv.to_s.sub(/^@/, '')}", nil, nil, true, false, Nodes::Scalar::ANY)
546
+ accept target.instance_variable_get(iv)
547
+ end
548
+ end
549
+ end
550
+ end
551
+ end