Module: YAML

Defined in:
lib/yaml/dbm.rb,
lib/yaml/tag.rb,
lib/yaml/syck.rb,
lib/yaml/error.rb,
lib/yaml/types.rb,
lib/yaml/ypath.rb,
lib/yaml/loader.rb,
lib/yaml/stream.rb,
lib/yaml/basenode.rb,
lib/yaml/encoding.rb,
lib/yaml/yamlnode.rb,
lib/yaml/constants.rb,
lib/rubysl/yaml/yaml.rb,
lib/yaml/baseemitter.rb

Overview

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

Defined Under Namespace

Modules: BaseEmitter, BaseNode, Syck Classes: DBM, DomainType, Error, Loader, Mapping, Object, Omap, Pairs, ParseError, PrivateType, Sequence, Set, SpecialHash, Store, Stream, TypeError, YPath, YamlNode

Constant Summary collapse

ERROR_NO_HEADER_NODE =

Error messages

"With UseHeader=false, the node Array or Hash must have elements"
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 =

Constants

'0.60'
SUPPORTED_YAML_VERSIONS =
['1.0']
WORD_CHAR =

Parser tokens

'A-Za-z0-9'
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 =

Default settings

{
	: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
}
Resolver =
YAML::Syck::Resolver
DefaultResolver =
YAML::Syck::DefaultResolver
GenericResolver =
YAML::Syck::GenericResolver
Parser =
YAML::Syck::Parser
Emitter =
YAML::Syck::Emitter
@@tagged_classes =

A dictionary of taguris which map to Ruby classes.

{}

Class Method Summary collapse

Class Method Details

.add_builtin_type(type_tag, &transfer_proc) ⇒ Object

Add a transfer method for a builtin type



306
307
308
# File 'lib/rubysl/yaml/yaml.rb', line 306

def YAML.add_builtin_type( type_tag, &transfer_proc )
    resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
end

.add_domain_type(domain, type_tag, &transfer_proc) ⇒ Object

Add a global handler for a YAML domain type.



299
300
301
# File 'lib/rubysl/yaml/yaml.rb', line 299

def YAML.add_domain_type( domain, type_tag, &transfer_proc )
       resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
end

.add_private_type(type_re, &transfer_proc) ⇒ Object

Add a private document type



320
321
322
# File 'lib/rubysl/yaml/yaml.rb', line 320

def YAML.add_private_type( type_re, &transfer_proc )
    resolver.add_type( "x-private:" + type_re, transfer_proc )
end

.add_ruby_type(type_tag, &transfer_proc) ⇒ Object

Add a transfer method for a builtin type



313
314
315
# File 'lib/rubysl/yaml/yaml.rb', line 313

def YAML.add_ruby_type( type_tag, &transfer_proc )
    resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
end

.detect_implicit(val) ⇒ Object

Detect typing of a string



327
328
329
# File 'lib/rubysl/yaml/yaml.rb', line 327

def YAML.detect_implicit( val )
    resolver.detect_implicit( val )
end

.dump(obj, io = nil) ⇒ Object

YAML.dump( :locked )

#=> "--- :locked"


116
117
118
119
# File 'lib/rubysl/yaml/yaml.rb', line 116

def YAML.dump( obj, io = nil )
       obj.to_yaml( io || io2 = StringIO.new )
       io || ( io2.rewind; io2.read )
end

.dump_stream(*objs) ⇒ Object

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

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


288
289
290
291
292
293
294
# File 'lib/rubysl/yaml/yaml.rb', line 288

def YAML.dump_stream( *objs )
	d = YAML::Stream.new
       objs.each do |doc|
		d.add( doc ) 
       end
       d.emit
end

.each_document(io, &block) ⇒ Object

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


216
217
218
# File 'lib/rubysl/yaml/yaml.rb', line 216

def YAML.each_document( io, &block )
		yp = parser.load_documents( io, &block )
end

.each_node(io, &doc_proc) ⇒ Object

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


246
247
248
# File 'lib/rubysl/yaml/yaml.rb', line 246

def YAML.each_node( io, &doc_proc )
		yp = generic_parser.load_documents( io, &doc_proc )
end

.emitterObject

Returns a new default emitter



101
# File 'lib/rubysl/yaml/yaml.rb', line 101

def YAML.emitter; Emitter.new.set_resolver( YAML.resolver ); end

.escape(value, skip = "") ⇒ Object

Escape the string, condensing common escapes



10
11
12
13
14
15
16
# File 'lib/yaml/encoding.rb', line 10

def YAML.escape( value, skip = "" )
	value.gsub( /\\/, "\\\\\\" ).
             gsub( /"/, "\\\"" ).
             gsub( /([\x00-\x1f])/ ) do |x|
                skip[x] || ESCAPES[ x.unpack("C")[0] ]
            end
end

.generic_parserObject

Returns a new generic parser



97
# File 'lib/rubysl/yaml/yaml.rb', line 97

def YAML.generic_parser; Parser.new.set_resolver( GenericResolver ); end

.load(io) ⇒ Object

File.open( ‘animals.yaml’ ) { |yf| YAML::load( yf ) }

#=> ['badger', 'elephant', 'tiger']

Can also load from a string.

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


132
133
134
# File 'lib/rubysl/yaml/yaml.rb', line 132

def YAML.load( io )
	yp = parser.load( io )
end

.load_documents(io, &doc_proc) ⇒ Object

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


231
232
233
# File 'lib/rubysl/yaml/yaml.rb', line 231

def YAML.load_documents( io, &doc_proc )
		YAML.each_document( io, &doc_proc )
end

.load_file(filepath) ⇒ Object

Load a document from the file located at filepath.

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


142
143
144
145
146
# File 'lib/rubysl/yaml/yaml.rb', line 142

def YAML.load_file( filepath )
    File.open( filepath ) do |f|
        load( f )
    end
end

.load_stream(io) ⇒ Object

returning a YAML::Stream object containing all loaded documents.



270
271
272
273
274
275
276
277
# File 'lib/rubysl/yaml/yaml.rb', line 270

def YAML.load_stream( io )
	d = nil
	parser.load_documents( io ) do |doc|
		d = YAML::Stream.new if not d
		d.add( doc ) 
       end
	return d
end

.object_maker(obj_class, val) ⇒ Object

Allocate blank object



365
366
367
368
369
370
371
372
373
374
375
# File 'lib/rubysl/yaml/yaml.rb', line 365

def YAML.object_maker( obj_class, val )
    if Hash === val
        o = obj_class.allocate
        val.each_pair { |k,v|
            o.instance_variable_set("@#{k}", v)
        }
        o
    else
        raise YAML::Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect
    end
end

.parse(io) ⇒ Object

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>


175
176
177
# File 'lib/rubysl/yaml/yaml.rb', line 175

def YAML.parse( io )
	yp = generic_parser.load( io )
end

.parse_documents(io, &doc_proc) ⇒ Object

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


261
262
263
# File 'lib/rubysl/yaml/yaml.rb', line 261

def YAML.parse_documents( io, &doc_proc )
		YAML.each_node( io, &doc_proc )
end

.parse_file(filepath) ⇒ Object

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">]>


199
200
201
202
203
# File 'lib/rubysl/yaml/yaml.rb', line 199

def YAML.parse_file( filepath )
    File.open( filepath ) do |f|
        parse( f )
    end
end

.parserObject

Returns a new default parser



95
# File 'lib/rubysl/yaml/yaml.rb', line 95

def YAML.parser; Parser.new.set_resolver( YAML.resolver ); end

.quick_emit(oid, opts = {}, &e) ⇒ Object

Allocate an Emitter if needed



380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/rubysl/yaml/yaml.rb', line 380

def YAML.quick_emit( oid, opts = {}, &e )
       out = 
           if opts.is_a? YAML::Emitter
               opts
           else
               emitter.reset( opts )
           end
       oid =
           case oid when Fixnum, NilClass; oid
           else oid = "#{oid.object_id}-#{oid.hash}"
           end
       out.emit( oid, &e )
end

.read_type_class(type, obj_class) ⇒ Object

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



356
357
358
359
360
# File 'lib/rubysl/yaml/yaml.rb', line 356

def YAML.read_type_class( type, obj_class )
    scheme, domain, type, tclass = type.split( ':', 4 )
    tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass
    return [ type, obj_class ]
end

.resolverObject

Returns the default resolver



99
# File 'lib/rubysl/yaml/yaml.rb', line 99

def YAML.resolver; DefaultResolver; end

.tag_class(tag, cls) ⇒ Object

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:[email protected],2004:notes/personal


35
36
37
38
39
40
# File 'lib/yaml/tag.rb', line 35

def YAML.tag_class( tag, cls )
    if @@tagged_classes.has_key? tag
        warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
    end
    @@tagged_classes[tag] = cls
end

.tagged_classesObject

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


48
49
50
# File 'lib/yaml/tag.rb', line 48

def YAML.tagged_classes
    @@tagged_classes
end

.tagurize(val) ⇒ Object

Convert a type_id to a taguri



334
335
336
# File 'lib/rubysl/yaml/yaml.rb', line 334

def YAML.tagurize( val )
    resolver.tagurize( val )
end

.transfer(type_id, obj) ⇒ Object

Apply a transfer method to a Ruby object



341
342
343
# File 'lib/rubysl/yaml/yaml.rb', line 341

def YAML.transfer( type_id, obj )
    resolver.transfer( YAML.tagurize( type_id ), obj )
end

.try_implicit(obj) ⇒ Object

Apply any implicit a node may qualify for



348
349
350
# File 'lib/rubysl/yaml/yaml.rb', line 348

def YAML.try_implicit( obj )
	YAML.transfer( YAML.detect_implicit( obj ), obj )
end

.unescape(value) ⇒ Object

Unescape the condenses escapes



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/yaml/encoding.rb', line 21

def YAML.unescape( value )
	value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) { |x| 
		if $3
			["#$3".hex ].pack('U*')
		elsif $2
			[$2].pack( "H2" ) 
		else
			UNESCAPES[$1] 
		end
	}
end