psych-with-location 3.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
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 +591 -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 +255 -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 +68 -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 +137 -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-with-location.gemspec +66 -0
  74. metadata +174 -0
@@ -0,0 +1,511 @@
1
+ # frozen_string_literal: true
2
+ require 'psych/versions'
3
+ case RUBY_ENGINE
4
+ when 'jruby'
5
+ require 'psych_jars'
6
+ org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
7
+ else
8
+ begin
9
+ require "#{RUBY_VERSION[/\d+\.\d+/]}/psych.so"
10
+ rescue LoadError
11
+ require 'psych.so'
12
+ end
13
+ end
14
+ require 'psych/nodes'
15
+ require 'psych/streaming'
16
+ require 'psych/visitors'
17
+ require 'psych/handler'
18
+ require 'psych/tree_builder'
19
+ require 'psych/parser'
20
+ require 'psych/omap'
21
+ require 'psych/set'
22
+ require 'psych/coder'
23
+ require 'psych/core_ext'
24
+ require 'psych/stream'
25
+ require 'psych/json/tree_builder'
26
+ require 'psych/json/stream'
27
+ require 'psych/handlers/document_stream'
28
+ require 'psych/class_loader'
29
+
30
+ ###
31
+ # = Overview
32
+ #
33
+ # Psych is a YAML parser and emitter.
34
+ # Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML]
35
+ # or [HG repo: https://bitbucket.org/xi/libyaml] for its YAML parsing
36
+ # and emitting capabilities. In addition to wrapping libyaml, Psych also
37
+ # knows how to serialize and de-serialize most Ruby objects to and from
38
+ # the YAML format.
39
+ #
40
+ # = I NEED TO PARSE OR EMIT YAML RIGHT NOW!
41
+ #
42
+ # # Parse some YAML
43
+ # Psych.load("--- foo") # => "foo"
44
+ #
45
+ # # Emit some YAML
46
+ # Psych.dump("foo") # => "--- foo\n...\n"
47
+ # { :a => 'b'}.to_yaml # => "---\n:a: b\n"
48
+ #
49
+ # Got more time on your hands? Keep on reading!
50
+ #
51
+ # == YAML Parsing
52
+ #
53
+ # Psych provides a range of interfaces for parsing a YAML document ranging from
54
+ # low level to high level, depending on your parsing needs. At the lowest
55
+ # level, is an event based parser. Mid level is access to the raw YAML AST,
56
+ # and at the highest level is the ability to unmarshal YAML to Ruby objects.
57
+ #
58
+ # == YAML Emitting
59
+ #
60
+ # Psych provides a range of interfaces ranging from low to high level for
61
+ # producing YAML documents. Very similar to the YAML parsing interfaces, Psych
62
+ # provides at the lowest level, an event based system, mid-level is building
63
+ # a YAML AST, and the highest level is converting a Ruby object straight to
64
+ # a YAML document.
65
+ #
66
+ # == High-level API
67
+ #
68
+ # === Parsing
69
+ #
70
+ # The high level YAML parser provided by Psych simply takes YAML as input and
71
+ # returns a Ruby data structure. For information on using the high level parser
72
+ # see Psych.load
73
+ #
74
+ # ==== Reading from a string
75
+ #
76
+ # Psych.load("--- a") # => 'a'
77
+ # Psych.load("---\n - a\n - b") # => ['a', 'b']
78
+ #
79
+ # ==== Reading from a file
80
+ #
81
+ # Psych.load_file("database.yml")
82
+ #
83
+ # ==== Exception handling
84
+ #
85
+ # begin
86
+ # # The second argument changes only the exception contents
87
+ # Psych.parse("--- `", "file.txt")
88
+ # rescue Psych::SyntaxError => ex
89
+ # ex.file # => 'file.txt'
90
+ # ex.message # => "(file.txt): found character that cannot start any token"
91
+ # end
92
+ #
93
+ # === Emitting
94
+ #
95
+ # The high level emitter has the easiest interface. Psych simply takes a Ruby
96
+ # data structure and converts it to a YAML document. See Psych.dump for more
97
+ # information on dumping a Ruby data structure.
98
+ #
99
+ # ==== Writing to a string
100
+ #
101
+ # # Dump an array, get back a YAML string
102
+ # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
103
+ #
104
+ # # Dump an array to an IO object
105
+ # Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
106
+ #
107
+ # # Dump an array with indentation set
108
+ # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
109
+ #
110
+ # # Dump an array to an IO with indentation set
111
+ # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
112
+ #
113
+ # ==== Writing to a file
114
+ #
115
+ # Currently there is no direct API for dumping Ruby structure to file:
116
+ #
117
+ # File.open('database.yml', 'w') do |file|
118
+ # file.write(Psych.dump(['a', 'b']))
119
+ # end
120
+ #
121
+ # == Mid-level API
122
+ #
123
+ # === Parsing
124
+ #
125
+ # Psych provides access to an AST produced from parsing a YAML document. This
126
+ # tree is built using the Psych::Parser and Psych::TreeBuilder. The AST can
127
+ # be examined and manipulated freely. Please see Psych::parse_stream,
128
+ # Psych::Nodes, and Psych::Nodes::Node for more information on dealing with
129
+ # YAML syntax trees.
130
+ #
131
+ # ==== Reading from a string
132
+ #
133
+ # # Returns Psych::Nodes::Stream
134
+ # Psych.parse_stream("---\n - a\n - b")
135
+ #
136
+ # # Returns Psych::Nodes::Document
137
+ # Psych.parse("---\n - a\n - b")
138
+ #
139
+ # ==== Reading from a file
140
+ #
141
+ # # Returns Psych::Nodes::Stream
142
+ # Psych.parse_stream(File.read('database.yml'))
143
+ #
144
+ # # Returns Psych::Nodes::Document
145
+ # Psych.parse_file('database.yml')
146
+ #
147
+ # ==== Exception handling
148
+ #
149
+ # begin
150
+ # # The second argument changes only the exception contents
151
+ # Psych.parse("--- `", "file.txt")
152
+ # rescue Psych::SyntaxError => ex
153
+ # ex.file # => 'file.txt'
154
+ # ex.message # => "(file.txt): found character that cannot start any token"
155
+ # end
156
+ #
157
+ # === Emitting
158
+ #
159
+ # At the mid level is building an AST. This AST is exactly the same as the AST
160
+ # used when parsing a YAML document. Users can build an AST by hand and the
161
+ # AST knows how to emit itself as a YAML document. See Psych::Nodes,
162
+ # Psych::Nodes::Node, and Psych::TreeBuilder for more information on building
163
+ # a YAML AST.
164
+ #
165
+ # ==== Writing to a string
166
+ #
167
+ # # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
168
+ # stream = Psych.parse_stream("---\n - a\n - b")
169
+ #
170
+ # stream.to_yaml # => "---\n- a\n- b\n"
171
+ #
172
+ # ==== Writing to a file
173
+ #
174
+ # # We need Psych::Nodes::Stream (not Psych::Nodes::Document)
175
+ # stream = Psych.parse_stream(File.read('database.yml'))
176
+ #
177
+ # File.open('database.yml', 'w') do |file|
178
+ # file.write(stream.to_yaml)
179
+ # end
180
+ #
181
+ # == Low-level API
182
+ #
183
+ # === Parsing
184
+ #
185
+ # The lowest level parser should be used when the YAML input is already known,
186
+ # and the developer does not want to pay the price of building an AST or
187
+ # automatic detection and conversion to Ruby objects. See Psych::Parser for
188
+ # more information on using the event based parser.
189
+ #
190
+ # ==== Reading to Psych::Nodes::Stream structure
191
+ #
192
+ # parser = Psych::Parser.new(TreeBuilder.new) # => #<Psych::Parser>
193
+ # parser = Psych.parser # it's an alias for the above
194
+ #
195
+ # parser.parse("---\n - a\n - b") # => #<Psych::Parser>
196
+ # parser.handler # => #<Psych::TreeBuilder>
197
+ # parser.handler.root # => #<Psych::Nodes::Stream>
198
+ #
199
+ # ==== Receiving an events stream
200
+ #
201
+ # parser = Psych::Parser.new(Psych::Handlers::Recorder.new)
202
+ #
203
+ # parser.parse("---\n - a\n - b")
204
+ # parser.events # => [list of [event, args] lists]
205
+ # # event is one of: Psych::Handler::EVENTS
206
+ # # args are the arguments passed to the event
207
+ #
208
+ # === Emitting
209
+ #
210
+ # The lowest level emitter is an event based system. Events are sent to a
211
+ # Psych::Emitter object. That object knows how to convert the events to a YAML
212
+ # document. This interface should be used when document format is known in
213
+ # advance or speed is a concern. See Psych::Emitter for more information.
214
+ #
215
+ # ==== Writing to a Ruby structure
216
+ #
217
+ # Psych.parser.parse("--- a") # => #<Psych::Parser>
218
+ #
219
+ # parser.handler.first # => #<Psych::Nodes::Stream>
220
+ # parser.handler.first.to_ruby # => ["a"]
221
+ #
222
+ # parser.handler.root.first # => #<Psych::Nodes::Document>
223
+ # parser.handler.root.first.to_ruby # => "a"
224
+ #
225
+ # # You can instantiate an Emitter manually
226
+ # Psych::Visitors::ToRuby.new.accept(parser.handler.root.first)
227
+ # # => "a"
228
+
229
+ module Psych
230
+ # The version of libyaml Psych is using
231
+ LIBYAML_VERSION = Psych.libyaml_version.join '.'
232
+
233
+ FALLBACK = Struct.new :to_ruby # :nodoc:
234
+
235
+ ###
236
+ # Load +yaml+ in to a Ruby data structure. If multiple documents are
237
+ # provided, the object contained in the first document will be returned.
238
+ # +filename+ will be used in the exception message if any exception is raised
239
+ # while parsing.
240
+ #
241
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
242
+ #
243
+ # Example:
244
+ #
245
+ # Psych.load("--- a") # => 'a'
246
+ # Psych.load("---\n - a\n - b") # => ['a', 'b']
247
+ #
248
+ # begin
249
+ # Psych.load("--- `", "file.txt")
250
+ # rescue Psych::SyntaxError => ex
251
+ # ex.file # => 'file.txt'
252
+ # ex.message # => "(file.txt): found character that cannot start any token"
253
+ # end
254
+ def self.load yaml, filename = nil, fallback = false
255
+ result = parse(yaml, filename, fallback)
256
+ result ? result.to_ruby : result
257
+ end
258
+
259
+ ###
260
+ # Safely load the yaml string in +yaml+. By default, only the following
261
+ # classes are allowed to be deserialized:
262
+ #
263
+ # * TrueClass
264
+ # * FalseClass
265
+ # * NilClass
266
+ # * Numeric
267
+ # * String
268
+ # * Array
269
+ # * Hash
270
+ #
271
+ # Recursive data structures are not allowed by default. Arbitrary classes
272
+ # can be allowed by adding those classes to the +whitelist+. They are
273
+ # additive. For example, to allow Date deserialization:
274
+ #
275
+ # Psych.safe_load(yaml, [Date])
276
+ #
277
+ # Now the Date class can be loaded in addition to the classes listed above.
278
+ #
279
+ # Aliases can be explicitly allowed by changing the +aliases+ parameter.
280
+ # For example:
281
+ #
282
+ # x = []
283
+ # x << x
284
+ # yaml = Psych.dump x
285
+ # Psych.safe_load yaml # => raises an exception
286
+ # Psych.safe_load yaml, [], [], true # => loads the aliases
287
+ #
288
+ # A Psych::DisallowedClass exception will be raised if the yaml contains a
289
+ # class that isn't in the whitelist.
290
+ #
291
+ # A Psych::BadAlias exception will be raised if the yaml contains aliases
292
+ # but the +aliases+ parameter is set to false.
293
+ def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil
294
+ result = parse(yaml, filename)
295
+ return unless result
296
+
297
+ class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
298
+ whitelist_symbols.map(&:to_s))
299
+ scanner = ScalarScanner.new class_loader
300
+ if aliases
301
+ visitor = Visitors::ToRuby.new scanner, class_loader
302
+ else
303
+ visitor = Visitors::NoAliasRuby.new scanner, class_loader
304
+ end
305
+ visitor.accept result
306
+ end
307
+
308
+ ###
309
+ # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Document.
310
+ # +filename+ is used in the exception message if a Psych::SyntaxError is
311
+ # raised.
312
+ #
313
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
314
+ #
315
+ # Example:
316
+ #
317
+ # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
318
+ #
319
+ # begin
320
+ # Psych.parse("--- `", "file.txt")
321
+ # rescue Psych::SyntaxError => ex
322
+ # ex.file # => 'file.txt'
323
+ # ex.message # => "(file.txt): found character that cannot start any token"
324
+ # end
325
+ #
326
+ # See Psych::Nodes for more information about YAML AST.
327
+ def self.parse yaml, filename = nil, fallback = false
328
+ parse_stream(yaml, filename) do |node|
329
+ return node
330
+ end
331
+ fallback
332
+ end
333
+
334
+ ###
335
+ # Parse a file at +filename+. Returns the Psych::Nodes::Document.
336
+ #
337
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
338
+ def self.parse_file filename
339
+ File.open filename, 'r:bom|utf-8' do |f|
340
+ parse f, filename
341
+ end
342
+ end
343
+
344
+ ###
345
+ # Returns a default parser
346
+ def self.parser
347
+ Psych::Parser.new(TreeBuilder.new)
348
+ end
349
+
350
+ ###
351
+ # Parse a YAML string in +yaml+. Returns the Psych::Nodes::Stream.
352
+ # This method can handle multiple YAML documents contained in +yaml+.
353
+ # +filename+ is used in the exception message if a Psych::SyntaxError is
354
+ # raised.
355
+ #
356
+ # If a block is given, a Psych::Nodes::Document node will be yielded to the
357
+ # block as it's being parsed.
358
+ #
359
+ # Raises a Psych::SyntaxError when a YAML syntax error is detected.
360
+ #
361
+ # Example:
362
+ #
363
+ # Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
364
+ #
365
+ # Psych.parse_stream("--- a\n--- b") do |node|
366
+ # node # => #<Psych::Nodes::Document:0x00>
367
+ # end
368
+ #
369
+ # begin
370
+ # Psych.parse_stream("--- `", "file.txt")
371
+ # rescue Psych::SyntaxError => ex
372
+ # ex.file # => 'file.txt'
373
+ # ex.message # => "(file.txt): found character that cannot start any token"
374
+ # end
375
+ #
376
+ # See Psych::Nodes for more information about YAML AST.
377
+ def self.parse_stream yaml, filename = nil, &block
378
+ if block_given?
379
+ parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
380
+ parser.parse yaml, filename
381
+ else
382
+ parser = self.parser
383
+ parser.parse yaml, filename
384
+ parser.handler.root
385
+ end
386
+ end
387
+
388
+ ###
389
+ # call-seq:
390
+ # Psych.dump(o) -> string of yaml
391
+ # Psych.dump(o, options) -> string of yaml
392
+ # Psych.dump(o, io) -> io object passed in
393
+ # Psych.dump(o, io, options) -> io object passed in
394
+ #
395
+ # Dump Ruby object +o+ to a YAML string. Optional +options+ may be passed in
396
+ # to control the output format. If an IO object is passed in, the YAML will
397
+ # be dumped to that IO object.
398
+ #
399
+ # Example:
400
+ #
401
+ # # Dump an array, get back a YAML string
402
+ # Psych.dump(['a', 'b']) # => "---\n- a\n- b\n"
403
+ #
404
+ # # Dump an array to an IO object
405
+ # Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890>
406
+ #
407
+ # # Dump an array with indentation set
408
+ # Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n"
409
+ #
410
+ # # Dump an array to an IO with indentation set
411
+ # Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
412
+ def self.dump o, io = nil, options = {}
413
+ if Hash === io
414
+ options = io
415
+ io = nil
416
+ end
417
+
418
+ visitor = Psych::Visitors::YAMLTree.create options
419
+ visitor << o
420
+ visitor.tree.yaml io, options
421
+ end
422
+
423
+ ###
424
+ # Dump a list of objects as separate documents to a document stream.
425
+ #
426
+ # Example:
427
+ #
428
+ # Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
429
+ def self.dump_stream *objects
430
+ visitor = Psych::Visitors::YAMLTree.create({})
431
+ objects.each do |o|
432
+ visitor << o
433
+ end
434
+ visitor.tree.yaml
435
+ end
436
+
437
+ ###
438
+ # Dump Ruby +object+ to a JSON string.
439
+ def self.to_json object
440
+ visitor = Psych::Visitors::JSONTree.create
441
+ visitor << object
442
+ visitor.tree.yaml
443
+ end
444
+
445
+ ###
446
+ # Load multiple documents given in +yaml+. Returns the parsed documents
447
+ # as a list. If a block is given, each document will be converted to Ruby
448
+ # and passed to the block during parsing
449
+ #
450
+ # Example:
451
+ #
452
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
453
+ #
454
+ # list = []
455
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
456
+ # list << ruby
457
+ # end
458
+ # list # => ['foo', 'bar']
459
+ #
460
+ def self.load_stream yaml, filename = nil
461
+ if block_given?
462
+ parse_stream(yaml, filename) do |node|
463
+ yield node.to_ruby
464
+ end
465
+ else
466
+ parse_stream(yaml, filename).children.map { |child| child.to_ruby }
467
+ end
468
+ end
469
+
470
+ ###
471
+ # Load the document contained in +filename+. Returns the yaml contained in
472
+ # +filename+ as a Ruby object, or if the file is empty, it returns
473
+ # the specified default return value, which defaults to an empty Hash
474
+ def self.load_file filename, fallback = false
475
+ File.open(filename, 'r:bom|utf-8') { |f|
476
+ self.load f, filename, FALLBACK.new(fallback)
477
+ }
478
+ end
479
+
480
+ # :stopdoc:
481
+ @domain_types = {}
482
+ def self.add_domain_type domain, type_tag, &block
483
+ key = ['tag', domain, type_tag].join ':'
484
+ @domain_types[key] = [key, block]
485
+ @domain_types["tag:#{type_tag}"] = [key, block]
486
+ end
487
+
488
+ def self.add_builtin_type type_tag, &block
489
+ domain = 'yaml.org,2002'
490
+ key = ['tag', domain, type_tag].join ':'
491
+ @domain_types[key] = [key, block]
492
+ end
493
+
494
+ def self.remove_type type_tag
495
+ @domain_types.delete type_tag
496
+ end
497
+
498
+ @load_tags = {}
499
+ @dump_tags = {}
500
+ def self.add_tag tag, klass
501
+ @load_tags[tag] = klass.name
502
+ @dump_tags[klass] = tag
503
+ end
504
+
505
+ class << self
506
+ attr_accessor :load_tags
507
+ attr_accessor :dump_tags
508
+ attr_accessor :domain_types
509
+ end
510
+ # :startdoc:
511
+ end