source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/yaml.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

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