Module YAML
In: lib/yaml/baseemitter.rb
lib/yaml/encoding.rb
lib/yaml/ypath.rb
lib/yaml/loader.rb
lib/yaml/dbm.rb
lib/yaml/error.rb
lib/yaml/tag.rb
lib/yaml/yamlnode.rb
lib/yaml/basenode.rb
lib/yaml/syck.rb
lib/yaml/types.rb
lib/yaml/stream.rb
lib/yaml/constants.rb
lib/yaml.rb

YAML

YAML(tm) (rhymes with ‘camel’) is a straightforward machine parsable data serialization format designed for human readability and interaction with scripting languages such as Perl and Python. YAML is optimized for data serialization, formatted dumping, configuration files, log files, Internet messaging and filtering. This specification describes the YAML information model and serialization format. Together with the Unicode standard for characters, it provides all the information necessary to understand YAML Version 1.0 and construct computer programs to process it.

See yaml.org/ for more information. For a quick tutorial, please visit YAML In Five Minutes (yaml.kwiki.org/?YamlInFiveMinutes).

About This Library

The YAML 1.0 specification outlines four stages of YAML loading and dumping. This library honors all four of those stages, although data is really only available to you in three stages.

The four stages are: native, representation, serialization, and presentation.

The native stage refers to data which has been loaded completely into Ruby‘s own types. (See +YAML::load+.)

The representation stage means data which has been composed into +YAML::BaseNode+ objects. In this stage, the document is available as a tree of node objects. You can perform YPath queries and transformations at this level. (See +YAML::parse+.)

The serialization stage happens inside the parser. The YAML parser used in Ruby is called Syck. Serialized nodes are available in the extension as SyckNode structs.

The presentation stage is the YAML document itself. This is accessible to you as a string. (See +YAML::dump+.)

For more information about the various information models, see Chapter 3 of the YAML 1.0 Specification (yaml.org/spec/#id2491269).

The YAML module provides quick access to the most common loading (YAML::load) and dumping (YAML::dump) tasks. This module also provides an API for registering global types (YAML::add_domain_type).

Example

A simple round-trip (load and dump) of an object.

    require "yaml"

    test_obj = ["dogs", "cats", "badgers"]

    yaml_obj = YAML::dump( test_obj )
                        # -> ---
                             - dogs
                             - cats
                             - badgers
    ruby_obj = YAML::load( yaml_obj )
                        # => ["dogs", "cats", "badgers"]
    ruby_obj == test_obj
                        # => true

To register your custom types with the global resolver, use add_domain_type.

    YAML::add_domain_type( "your-site.com,2004", "widget" ) do |type, val|
        Widget.new( val )
    end

Methods

Classes and Modules

Module YAML::BaseEmitter
Module YAML::BaseNode
Module YAML::Syck
Class YAML::DBM
Class YAML::DomainType
Class YAML::Error
Class YAML::Loader
Class YAML::Mapping
Class YAML::Object
Class YAML::Omap
Class YAML::Pairs
Class YAML::ParseError
Class YAML::PrivateType
Class YAML::Sequence
Class YAML::Set
Class YAML::SpecialHash
Class YAML::Store
Class YAML::Stream
Class YAML::TypeError
Class YAML::YPath
Class YAML::YamlNode

Constants

ERROR_NO_HEADER_NODE = "With UseHeader=false, the node Array or Hash must have elements"   Error messages
ERROR_NEED_HEADER = "With UseHeader=false, the node must be an Array or Hash"
ERROR_BAD_EXPLICIT = "Unsupported explicit transfer: '%s'"
ERROR_MANY_EXPLICIT = "More than one explicit transfer"
ERROR_MANY_IMPLICIT = "More than one implicit request"
ERROR_NO_ANCHOR = "No anchor for alias '%s'"
ERROR_BAD_ANCHOR = "Invalid anchor: %s"
ERROR_MANY_ANCHOR = "More than one anchor"
ERROR_ANCHOR_ALIAS = "Can't define both an anchor and an alias"
ERROR_BAD_ALIAS = "Invalid alias: %s"
ERROR_MANY_ALIAS = "More than one alias"
ERROR_ZERO_INDENT = "Can't use zero as an indentation width"
ERROR_UNSUPPORTED_VERSION = "This release of YAML.rb does not support YAML version %s"
ERROR_UNSUPPORTED_ENCODING = "Attempt to use unsupported encoding: %s"
VERSION = '0.60'   Constants
SUPPORTED_YAML_VERSIONS = ['1.0']
WORD_CHAR = 'A-Za-z0-9'   Parser tokens
PRINTABLE_CHAR = '-_A-Za-z0-9!?/()$\'". '
NOT_PLAIN_CHAR = '\x7f\x0-\x1f\x80-\x9f'
ESCAPE_CHAR = '[\\x00-\\x09\\x0b-\\x1f]'
INDICATOR_CHAR = '*&!|\\\\^@%{}[]='
SPACE_INDICATORS = '-#:,?'
RESTRICTED_INDICATORS = '#:,}]'
DNS_COMP_RE = "\\w(?:[-\\w]*\\w)?"
DNS_NAME_RE = "(?:(?:#{DNS_COMP_RE}\\.)+#{DNS_COMP_RE}|#{DNS_COMP_RE})"
ESCAPES = %w{\x00 \x01 \x02 \x03 \x04 \x05 \x06 \a \x08 \t \n \v \f \r \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \e \x1c \x1d \x1e \x1f }
UNESCAPES = { 'a' => "\x07", 'b' => "\x08", 't' => "\x09", 'n' => "\x0a", 'v' => "\x0b", 'f' => "\x0c", 'r' => "\x0d", 'e' => "\x1b", '\\' => '\\', }
DEFAULTS = { :Indent => 2, :UseHeader => false, :UseVersion => false, :Version => '1.0', :SortKeys => false, :AnchorFormat => 'id%03d', :ExplicitTypes => false, :WidthType => 'absolute', :BestWidth => 80, :UseBlock => false, :UseFold => false, :Encoding => :None   Default settings
Resolver = YAML::Syck::Resolver
DefaultResolver = YAML::Syck::DefaultResolver
GenericResolver = YAML::Syck::GenericResolver
Parser = YAML::Syck::Parser
Emitter = YAML::Syck::Emitter

Public Class methods

Add a transfer method for a builtin type

[Source]

     # File lib/yaml.rb, line 306
306:         def YAML.add_builtin_type( type_tag, &transfer_proc )
307:             resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
308:         end

Add a global handler for a YAML domain type.

[Source]

     # File lib/yaml.rb, line 299
299:         def YAML.add_domain_type( domain, type_tag, &transfer_proc )
300:         resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
301:         end

Add a private document type

[Source]

     # File lib/yaml.rb, line 320
320:         def YAML.add_private_type( type_re, &transfer_proc )
321:             resolver.add_type( "x-private:" + type_re, transfer_proc )
322:         end

Add a transfer method for a builtin type

[Source]

     # File lib/yaml.rb, line 313
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

Detect typing of a string

[Source]

     # File lib/yaml.rb, line 327
327:     def YAML.detect_implicit( val )
328:         resolver.detect_implicit( val )
329:     end

Converts obj to YAML and writes the YAML result to io.

  File.open( 'animals.yaml', 'w' ) do |out|
    YAML.dump( ['badger', 'elephant', 'tiger'], out )
  end

If no io is provided, a string containing the dumped YAML is returned.

  YAML.dump( :locked )
     #=> "--- :locked"

[Source]

     # File lib/yaml.rb, line 116
116:         def YAML.dump( obj, io = nil )
117:         obj.to_yaml( io || io2 = StringIO.new )
118:         io || ( io2.rewind; io2.read )
119:         end

Returns a YAML stream containing each of the items in objs, each having their own document.

  YAML.dump_stream( 0, [], {} )
    #=> --- 0
        --- []
        --- {}

[Source]

     # File lib/yaml.rb, line 288
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

Calls block with each consecutive document in the YAML stream contained in io.

  File.open( 'many-docs.yaml' ) do |yf|
    YAML.each_document( yf ) do |ydoc|
      ## ydoc contains the single object
      ## from the YAML document
    end
  end

[Source]

     # File lib/yaml.rb, line 216
216:         def YAML.each_document( io, &block )
217:                 yp = parser.load_documents( io, &block )
218:     end

Calls block with a tree of +YAML::BaseNodes+, one tree for each consecutive document in the YAML stream contained in io.

  File.open( 'many-docs.yaml' ) do |yf|
    YAML.each_node( yf ) do |ydoc|
      ## ydoc contains a tree of nodes
      ## from the YAML document
    end
  end

[Source]

     # File lib/yaml.rb, line 246
246:         def YAML.each_node( io, &doc_proc )
247:                 yp = generic_parser.load_documents( io, &doc_proc )
248:     end

Returns a new default emitter

[Source]

     # File lib/yaml.rb, line 101
101:     def YAML.emitter; Emitter.new.set_resolver( YAML.resolver ); end

Escape the string, condensing common escapes

[Source]

    # File lib/yaml/encoding.rb, line 10
10:         def YAML.escape( value, skip = "" )
11:                 value.gsub( /\\/, "\\\\\\" ).
12:               gsub( /"/, "\\\"" ).
13:               gsub( /([\x00-\x1f])/ ) do
14:                  skip[$&] || ESCAPES[ $&.unpack("C")[0] ]
15:              end
16:         end

Returns a new generic parser

[Source]

    # File lib/yaml.rb, line 97
97:     def YAML.generic_parser; Parser.new.set_resolver( GenericResolver ); end

Load a document from the current io stream.

  File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
     #=> ['badger', 'elephant', 'tiger']

Can also load from a string.

  YAML.load( "--- :locked" )
     #=> :locked

[Source]

     # File lib/yaml.rb, line 132
132:         def YAML.load( io )
133:                 yp = parser.load( io )
134:         end

Calls block with each consecutive document in the YAML stream contained in io.

  File.open( 'many-docs.yaml' ) do |yf|
    YAML.load_documents( yf ) do |ydoc|
      ## ydoc contains the single object
      ## from the YAML document
    end
  end

[Source]

     # File lib/yaml.rb, line 231
231:         def YAML.load_documents( io, &doc_proc )
232:                 YAML.each_document( io, &doc_proc )
233:     end

Load a document from the file located at filepath.

  YAML.load_file( 'animals.yaml' )
     #=> ['badger', 'elephant', 'tiger']

[Source]

     # File lib/yaml.rb, line 142
142:     def YAML.load_file( filepath )
143:         File.open( filepath ) do |f|
144:             load( f )
145:         end
146:     end

Loads all documents from the current io stream, returning a +YAML::Stream+ object containing all loaded documents.

[Source]

     # File lib/yaml.rb, line 270
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

Class method for creating streams

[Source]

    # File lib/yaml/stringio.rb, line 55
55:         def YAML.make_stream( io )
56:         if String === io
57:             io = StringIO.new( io )
58:         elsif not IO === io
59:             raise YAML::Error, "YAML stream must be an IO or String object."
60:         end
61:         if YAML::unicode
62:             def io.readline
63:                 YAML.utf_to_internal( readline( @ln_sep ), @utf_encoding )
64:             end
65:             def io.check_unicode
66:                 @utf_encoding = YAML.sniff_encoding( read( 4 ) )
67:                 @ln_sep = YAML.enc_separator( @utf_encoding )
68:                 seek( -4, IO::SEEK_CUR )
69:             end
70:                     def io.utf_encoding
71:                       @utf_encoding
72:                     end
73:             io.check_unicode
74:         else
75:             def io.utf_encoding
76:                 :None
77:             end
78:         end
79:         io
80:         end

Allocate blank object

[Source]

     # File lib/yaml.rb, line 365
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

Parse the first document from the current io stream

  File.open( 'animals.yaml' ) { |yf| YAML::load( yf ) }
     #=> #<YAML::Syck::Node:0x82ccce0
          @kind=:seq,
          @value=
           [#<YAML::Syck::Node:0x82ccd94
             @kind=:scalar,
             @type_id="str",
             @value="badger">,
            #<YAML::Syck::Node:0x82ccd58
             @kind=:scalar,
             @type_id="str",
             @value="elephant">,
            #<YAML::Syck::Node:0x82ccd1c
             @kind=:scalar,
             @type_id="str",
             @value="tiger">]>

Can also load from a string.

  YAML.parse( "--- :locked" )
     #=> #<YAML::Syck::Node:0x82edddc
           @type_id="tag:ruby.yaml.org,2002:sym",
           @value=":locked", @kind=:scalar>

[Source]

     # File lib/yaml.rb, line 175
175:         def YAML.parse( io )
176:                 yp = generic_parser.load( io )
177:         end

Calls block with a tree of +YAML::BaseNodes+, one tree for each consecutive document in the YAML stream contained in io.

  File.open( 'many-docs.yaml' ) do |yf|
    YAML.parse_documents( yf ) do |ydoc|
      ## ydoc contains a tree of nodes
      ## from the YAML document
    end
  end

[Source]

     # File lib/yaml.rb, line 261
261:         def YAML.parse_documents( io, &doc_proc )
262:                 YAML.each_node( io, &doc_proc )
263:     end

Parse a document from the file located at filepath.

  YAML.parse_file( 'animals.yaml' )
     #=> #<YAML::Syck::Node:0x82ccce0
          @kind=:seq,
          @value=
           [#<YAML::Syck::Node:0x82ccd94
             @kind=:scalar,
             @type_id="str",
             @value="badger">,
            #<YAML::Syck::Node:0x82ccd58
             @kind=:scalar,
             @type_id="str",
             @value="elephant">,
            #<YAML::Syck::Node:0x82ccd1c
             @kind=:scalar,
             @type_id="str",
             @value="tiger">]>

[Source]

     # File lib/yaml.rb, line 199
199:     def YAML.parse_file( filepath )
200:         File.open( filepath ) do |f|
201:             parse( f )
202:         end
203:     end

Returns a new default parser

[Source]

    # File lib/yaml.rb, line 95
95:     def YAML.parser; Parser.new.set_resolver( YAML.resolver ); end

Allocate an Emitter if needed

[Source]

     # File lib/yaml.rb, line 380
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:         oid =
388:             case oid when Fixnum, NilClass; oid
389:             else oid = "#{oid.object_id}-#{oid.hash}"
390:             end
391:         out.emit( oid, &e )
392:         end

Method to extract colon-seperated type and class, returning the type and the constant of the class

[Source]

     # File lib/yaml.rb, line 356
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

Returns the default resolver

[Source]

    # File lib/yaml.rb, line 99
99:     def YAML.resolver; DefaultResolver; end

Associates a taguri tag with a Ruby class cls. The taguri is used to give types to classes when loading YAML. Taguris are of the form:

  tag:authorityName,date:specific

The authorityName is a domain name or email address. The date is the date the type was issued in YYYY or YYYY-MM or YYYY-MM-DD format. The specific is a name for the type being added.

For example, built-in YAML types have ‘yaml.org’ as the authorityName and ‘2002’ as the date. The specific is simply the name of the type:

 tag:yaml.org,2002:int
 tag:yaml.org,2002:float
 tag:yaml.org,2002:timestamp

The domain must be owned by you on the date declared. If you don‘t own any domains on the date you declare the type, you can simply use an e-mail address.

 tag:why@ruby-lang.org,2004:notes/personal

[Source]

    # File lib/yaml/tag.rb, line 35
35:     def YAML.tag_class( tag, cls )
36:         if @@tagged_classes.has_key? tag
37:             warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
38:         end
39:         @@tagged_classes[tag] = cls
40:     end

Returns the complete dictionary of taguris, paired with classes. The key for the dictionary is the full taguri. The value for each key is the class constant associated to that taguri.

 YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer

[Source]

    # File lib/yaml/tag.rb, line 48
48:     def YAML.tagged_classes
49:         @@tagged_classes
50:     end

Convert a type_id to a taguri

[Source]

     # File lib/yaml.rb, line 334
334:     def YAML.tagurize( val )
335:         resolver.tagurize( val )
336:     end

Apply a transfer method to a Ruby object

[Source]

     # File lib/yaml.rb, line 341
341:     def YAML.transfer( type_id, obj )
342:         resolver.transfer( YAML.tagurize( type_id ), obj )
343:     end

Apply any implicit a node may qualify for

[Source]

     # File lib/yaml.rb, line 348
348:         def YAML.try_implicit( obj )
349:                 YAML.transfer( YAML.detect_implicit( obj ), obj )
350:         end

Unescape the condenses escapes

[Source]

    # File lib/yaml/encoding.rb, line 21
21:         def YAML.unescape( value )
22:                 value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) {
23:                         if $3
24:                                 ["#$3".hex ].pack('U*')
25:                         elsif $2
26:                                 [$2].pack( "H2" ) 
27:                         else
28:                                 UNESCAPES[$1] 
29:                         end
30:                 }
31:         end

[Validate]