rubysl-yaml 2.0.4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,498 +0,0 @@
1
- # -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
2
- # $Id: syck.rb 28681 2010-07-19 04:54:06Z tenderlove $
3
- #
4
- # = yaml.rb: top-level module with methods for loading and parsing YAML documents
5
- #
6
- # Author:: why the lucky stiff
7
- #
8
-
9
- require 'stringio'
10
- require 'syck/syck'
11
- require 'syck/error'
12
- require 'syck/basenode'
13
- require 'syck/tag'
14
- require 'syck/stream'
15
- require 'syck/constants'
16
- require 'syck/rubytypes'
17
- require 'syck/types'
18
-
19
- # == YAML
20
- #
21
- # YAML(tm) (rhymes with 'camel') is a
22
- # straightforward machine parsable data serialization format designed for
23
- # human readability and interaction with scripting languages such as Perl
24
- # and Python. YAML is optimized for data serialization, formatted
25
- # dumping, configuration files, log files, Internet messaging and
26
- # filtering. This specification describes the YAML information model and
27
- # serialization format. Together with the Unicode standard for characters, it
28
- # provides all the information necessary to understand YAML Version 1.0
29
- # and construct computer programs to process it.
30
- #
31
- # See http://yaml.org/ for more information. For a quick tutorial, please
32
- # visit YAML In Five Minutes (http://yaml.kwiki.org/?YamlInFiveMinutes).
33
- #
34
- # == About This Library
35
- #
36
- # The YAML 1.0 specification outlines four stages of YAML loading and dumping.
37
- # This library honors all four of those stages, although data is really only
38
- # available to you in three stages.
39
- #
40
- # The four stages are: native, representation, serialization, and presentation.
41
- #
42
- # The native stage refers to data which has been loaded completely into Ruby's
43
- # own types. (See +YAML::load+.)
44
- #
45
- # The representation stage means data which has been composed into
46
- # +YAML::BaseNode+ objects. In this stage, the document is available as a
47
- # tree of node objects. You can perform YPath queries and transformations
48
- # at this level. (See +YAML::parse+.)
49
- #
50
- # The serialization stage happens inside the parser. The YAML parser used in
51
- # Ruby is called Syck. Serialized nodes are available in the extension as
52
- # SyckNode structs.
53
- #
54
- # The presentation stage is the YAML document itself. This is accessible
55
- # to you as a string. (See +YAML::dump+.)
56
- #
57
- # For more information about the various information models, see Chapter
58
- # 3 of the YAML 1.0 Specification (http://yaml.org/spec/#id2491269).
59
- #
60
- # The YAML module provides quick access to the most common loading (YAML::load)
61
- # and dumping (YAML::dump) tasks. This module also provides an API for registering
62
- # global types (YAML::add_domain_type).
63
- #
64
- # == Example
65
- #
66
- # A simple round-trip (load and dump) of an object.
67
- #
68
- # require "yaml"
69
- #
70
- # test_obj = ["dogs", "cats", "badgers"]
71
- #
72
- # yaml_obj = YAML::dump( test_obj )
73
- # # -> ---
74
- # - dogs
75
- # - cats
76
- # - badgers
77
- # ruby_obj = YAML::load( yaml_obj )
78
- # # => ["dogs", "cats", "badgers"]
79
- # ruby_obj == test_obj
80
- # # => true
81
- #
82
- # To register your custom types with the global resolver, use +add_domain_type+.
83
- #
84
- # YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val|
85
- # Widget.new( val )
86
- # end
87
- #
88
- module Syck
89
-
90
- DefaultResolver.use_types_at( @@tagged_classes )
91
-
92
- # Returns a new default parser
93
- def self.parser; Parser.new.set_resolver( self.resolver ); end
94
-
95
- # Returns a new generic parser
96
- def self.generic_parser
97
- warn "#{caller[0]}: YAML.generic_parser is deprecated, switch to psych" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
98
- Parser.new.set_resolver( GenericResolver )
99
- end
100
-
101
- # Returns the default resolver
102
- def self.resolver
103
- warn "#{caller[0]}: YAML.resolver is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
104
- DefaultResolver
105
- end
106
-
107
- # Returns a new default emitter
108
- def self.emitter
109
- warn "#{caller[0]}: YAML.emitter is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
110
- Emitter.new.set_resolver( self.resolver )
111
- end
112
-
113
- #
114
- # Converts _obj_ to YAML and writes the YAML result to _io_.
115
- #
116
- # File.open( 'animals.yaml', 'w' ) do |out|
117
- # YAML.dump( ['badger', 'elephant', 'tiger'], out )
118
- # end
119
- #
120
- # If no _io_ is provided, a string containing the dumped YAML
121
- # is returned.
122
- #
123
- # YAML.dump( :locked )
124
- # #=> "--- :locked"
125
- #
126
- def self.dump( obj, io = nil )
127
- obj.to_yaml( io || io2 = StringIO.new )
128
- io || ( io2.rewind; io2.read )
129
- end
130
-
131
- #
132
- # Load a document from the current _io_ stream.
133
- #
134
- # File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
135
- # #=> ['badger', 'elephant', 'tiger']
136
- #
137
- # Can also load from a string.
138
- #
139
- # YAML.load( "--- :locked" )
140
- # #=> :locked
141
- #
142
- def self.load( io )
143
- parser.load( io )
144
- end
145
-
146
- #
147
- # Load a document from the file located at _filepath_.
148
- #
149
- # YAML.load_file( 'animals.yaml' )
150
- # #=> ['badger', 'elephant', 'tiger']
151
- #
152
- def self.load_file( filepath )
153
- File.open( filepath ) do |f|
154
- load( f )
155
- end
156
- end
157
-
158
- #
159
- # Parse the first document from the current _io_ stream
160
- #
161
- # File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
162
- # #=> #<YAML::Syck::Node:0x82ccce0
163
- # @kind=:seq,
164
- # @value=
165
- # [#<YAML::Syck::Node:0x82ccd94
166
- # @kind=:scalar,
167
- # @type_id="str",
168
- # @value="badger">,
169
- # #<YAML::Syck::Node:0x82ccd58
170
- # @kind=:scalar,
171
- # @type_id="str",
172
- # @value="elephant">,
173
- # #<YAML::Syck::Node:0x82ccd1c
174
- # @kind=:scalar,
175
- # @type_id="str",
176
- # @value="tiger">]>
177
- #
178
- # Can also load from a string.
179
- #
180
- # YAML.parse( "--- :locked" )
181
- # #=> #<YAML::Syck::Node:0x82edddc
182
- # @type_id="tag:ruby.yaml.org,2002:sym",
183
- # @value=":locked", @kind=:scalar>
184
- #
185
- def self.parse( io )
186
- generic_parser.load( io )
187
- end
188
-
189
- #
190
- # Parse a document from the file located at _filepath_.
191
- #
192
- # YAML.parse_file( 'animals.yaml' )
193
- # #=> #<YAML::Syck::Node:0x82ccce0
194
- # @kind=:seq,
195
- # @value=
196
- # [#<YAML::Syck::Node:0x82ccd94
197
- # @kind=:scalar,
198
- # @type_id="str",
199
- # @value="badger">,
200
- # #<YAML::Syck::Node:0x82ccd58
201
- # @kind=:scalar,
202
- # @type_id="str",
203
- # @value="elephant">,
204
- # #<YAML::Syck::Node:0x82ccd1c
205
- # @kind=:scalar,
206
- # @type_id="str",
207
- # @value="tiger">]>
208
- #
209
- def self.parse_file( filepath )
210
- File.open( filepath ) do |f|
211
- parse( f )
212
- end
213
- end
214
-
215
- #
216
- # Calls _block_ with each consecutive document in the YAML
217
- # stream contained in _io_.
218
- #
219
- # File.open( 'many-docs.yaml' ) do |yf|
220
- # YAML.each_document( yf ) do |ydoc|
221
- # ## ydoc contains the single object
222
- # ## from the YAML document
223
- # end
224
- # end
225
- #
226
- def self.each_document( io, &block )
227
- warn "#{caller[0]}: YAML.each_document is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
228
- parser.load_documents( io, &block )
229
- end
230
-
231
- #
232
- # Calls _block_ with each consecutive document in the YAML
233
- # stream contained in _io_.
234
- #
235
- # File.open( 'many-docs.yaml' ) do |yf|
236
- # YAML.load_documents( yf ) do |ydoc|
237
- # ## ydoc contains the single object
238
- # ## from the YAML document
239
- # end
240
- # end
241
- #
242
- def self.load_documents( io, &doc_proc )
243
- parser.load_documents( io, &doc_proc )
244
- end
245
-
246
- #
247
- # Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
248
- # each consecutive document in the YAML stream contained in _io_.
249
- #
250
- # File.open( 'many-docs.yaml' ) do |yf|
251
- # YAML.each_node( yf ) do |ydoc|
252
- # ## ydoc contains a tree of nodes
253
- # ## from the YAML document
254
- # end
255
- # end
256
- #
257
- def self.each_node( io, &doc_proc )
258
- warn "#{caller[0]}: YAML.each_node is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
259
- generic_parser.load_documents( io, &doc_proc )
260
- end
261
-
262
- #
263
- # Calls _block_ with a tree of +YAML::BaseNodes+, one tree for
264
- # each consecutive document in the YAML stream contained in _io_.
265
- #
266
- # File.open( 'many-docs.yaml' ) do |yf|
267
- # YAML.parse_documents( yf ) do |ydoc|
268
- # ## ydoc contains a tree of nodes
269
- # ## from the YAML document
270
- # end
271
- # end
272
- #
273
- def self.parse_documents( io, &doc_proc )
274
- warn "#{caller[0]}: YAML.parse_documents is deprecated, use load_stream" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
275
- self.each_node( io, &doc_proc )
276
- end
277
-
278
- #
279
- # Loads all documents from the current _io_ stream,
280
- # returning a +YAML::Stream+ object containing all
281
- # loaded documents.
282
- #
283
- def self.load_stream( io )
284
- d = nil
285
- parser.load_documents( io ) do |doc|
286
- d = Stream.new if not d
287
- d.add( doc )
288
- end
289
- return d
290
- end
291
-
292
- #
293
- # Returns a YAML stream containing each of the items in +objs+,
294
- # each having their own document.
295
- #
296
- # YAML.dump_stream( 0, [], {} )
297
- # #=> --- 0
298
- # --- []
299
- # --- {}
300
- #
301
- def self.dump_stream( *objs )
302
- d = Stream.new
303
- objs.each do |doc|
304
- d.add( doc )
305
- end
306
- d.emit
307
- end
308
-
309
- #
310
- # Add a global handler for a YAML domain type.
311
- #
312
- def self.add_domain_type( domain, type_tag, &transfer_proc )
313
- resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
314
- end
315
-
316
- #
317
- # Add a transfer method for a builtin type
318
- #
319
- def self.add_builtin_type( type_tag, &transfer_proc )
320
- resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
321
- end
322
-
323
- #
324
- # Add a transfer method for a builtin type
325
- #
326
- def self.add_ruby_type( type_tag, &transfer_proc )
327
- warn "#{caller[0]}: YAML.add_ruby_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
328
- resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
329
- end
330
-
331
- #
332
- # Add a private document type
333
- #
334
- def self.add_private_type( type_re, &transfer_proc )
335
- warn "#{caller[0]}: YAML.add_private_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
336
- resolver.add_type( "x-private:" + type_re, transfer_proc )
337
- end
338
-
339
- #
340
- # Detect typing of a string
341
- #
342
- def self.detect_implicit( val )
343
- warn "#{caller[0]}: YAML.detect_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
344
- resolver.detect_implicit( val )
345
- end
346
-
347
- #
348
- # Convert a type_id to a taguri
349
- #
350
- def self.tagurize( val )
351
- warn "#{caller[0]}: YAML.tagurize is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
352
- resolver.tagurize( val )
353
- end
354
-
355
- #
356
- # Apply a transfer method to a Ruby object
357
- #
358
- def self.transfer( type_id, obj )
359
- warn "#{caller[0]}: YAML.transfer is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
360
- resolver.transfer( tagurize( type_id ), obj )
361
- end
362
-
363
- #
364
- # Apply any implicit a node may qualify for
365
- #
366
- def self.try_implicit( obj )
367
- warn "#{caller[0]}: YAML.try_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
368
- transfer( detect_implicit( obj ), obj )
369
- end
370
-
371
- #
372
- # Method to extract colon-seperated type and class, returning
373
- # the type and the constant of the class
374
- #
375
- def self.read_type_class( type, obj_class )
376
- warn "#{caller[0]}: YAML.read_type_class is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
377
- type, tclass = type.split( ':', 4 ).last(2)
378
- tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass
379
- return [ type, obj_class ]
380
- end
381
-
382
- #
383
- # Allocate blank object
384
- #
385
- def self.object_maker( obj_class, val )
386
- warn "#{caller[0]}: YAML.object_maker is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
387
- if Hash === val
388
- o = obj_class.allocate
389
- val.each_pair { |k,v|
390
- o.instance_variable_set("@#{k}", v)
391
- }
392
- o
393
- else
394
- raise Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
395
- end
396
- end
397
-
398
- #
399
- # Allocate an Emitter if needed
400
- #
401
- def self.quick_emit( oid, opts = {}, &e )
402
- warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__))
403
- out =
404
- if opts.is_a? Emitter
405
- opts
406
- else
407
- emitter.reset( opts )
408
- end
409
- out.emit( oid, &e )
410
- end
411
-
412
- #--
413
- # For Rubinius, replaces the rb_iterate call to syck_set_ivars.
414
- #++
415
- def self.set_ivars(hsh, obj)
416
- hsh.each do |key, value|
417
- obj.instance_variable_set :"@#{key}", value
418
- end
419
- end
420
-
421
- #--
422
- # For Rubinius, replaces the rb_iterate call to syck_merge_i.
423
- #++
424
- def self.merge_i(ary, hsh)
425
- ary.each do |entry|
426
- begin
427
- entry = Rubinius::Type.coerce_to entry, Hash, :to_hash
428
- hsh.update entry
429
- rescue
430
- # ignore coercion errors
431
- end
432
- end
433
-
434
- nil
435
- end
436
-
437
- #--
438
- # For Rubinius, replaces rb_syck_mktime.
439
- #++
440
- def self.mktime(str)
441
- require "date"
442
- begin
443
- DateTime.parse(str).to_time
444
- rescue ArgumentError
445
- # nothing
446
- end
447
- end
448
-
449
- #--
450
- # For Rubinius, replaces 'rb_require("date")' because that is hard-coded
451
- # to use Kernel.require, so RubyGems #require override isn't invoked.
452
- def self.require_date
453
- require "date"
454
- end
455
- end
456
-
457
- module Kernel
458
- #
459
- # ryan:: You know how Kernel.p is a really convenient way to dump ruby
460
- # structures? The only downside is that it's not as legible as
461
- # YAML.
462
- #
463
- # _why:: (listening)
464
- #
465
- # ryan:: I know you don't want to urinate all over your users' namespaces.
466
- # But, on the other hand, convenience of dumping for debugging is,
467
- # IMO, a big YAML use case.
468
- #
469
- # _why:: Go nuts! Have a pony parade!
470
- #
471
- # ryan:: Either way, I certainly will have a pony parade.
472
- #
473
-
474
- # Prints any supplied _objects_ out in YAML. Intended as
475
- # a variation on +Kernel::p+.
476
- #
477
- # S = Struct.new(:name, :state)
478
- # s = S['dave', 'TX']
479
- # y s
480
- #
481
- # _produces:_
482
- #
483
- # --- !ruby/struct:S
484
- # name: dave
485
- # state: TX
486
- #
487
- def y( object, *objects )
488
- objects.unshift object
489
- puts( if objects.length == 1
490
- YAML.dump( *objects )
491
- else
492
- YAML.dump_stream( *objects )
493
- end )
494
- end
495
- private :y
496
- end
497
-
498
-