module Syck
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
YAML::BaseNode class
Constants used throughout the library
Handle Unicode-to-Internal conversion
Error
messages and exception class
YAML::Loader class .. type handling ..
$Id$
yaml/tag.rb: methods for associating a taguri to a class.¶ ↑
- Author
-
why the lucky stiff
Classes required by the full core typeset
Constants
- DEFAULTS
Default settings
- DNS_COMP_RE
- DNS_NAME_RE
- ERROR_ANCHOR_ALIAS
- ERROR_BAD_ALIAS
- ERROR_BAD_ANCHOR
- ERROR_BAD_EXPLICIT
- ERROR_MANY_ALIAS
- ERROR_MANY_ANCHOR
- ERROR_MANY_EXPLICIT
- ERROR_MANY_IMPLICIT
- ERROR_NEED_HEADER
- ERROR_NO_ANCHOR
- ERROR_NO_HEADER_NODE
Error
messages- ERROR_UNSUPPORTED_ENCODING
- ERROR_UNSUPPORTED_VERSION
- ERROR_ZERO_INDENT
- ESCAPES
- ESCAPE_CHAR
- INDICATOR_CHAR
- NOT_PLAIN_CHAR
- PRINTABLE_CHAR
- RESTRICTED_INDICATORS
- SPACE_INDICATORS
- SUPPORTED_YAML_VERSIONS
- UNESCAPES
- VERSION
Constants
- WORD_CHAR
Parser tokens
Public Class Methods
Add a transfer method for a builtin type
# File lib/syck.rb, line 317 def self.add_builtin_type( type_tag, &transfer_proc ) resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc ) end
Add a global handler for a YAML domain type.
# File lib/syck.rb, line 310 def self.add_domain_type( domain, type_tag, &transfer_proc ) resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc ) end
Add a private document type
# File lib/syck.rb, line 332 def self.add_private_type( type_re, &transfer_proc ) warn "#{caller[0]}: YAML.add_private_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) resolver.add_type( "x-private:" + type_re, transfer_proc ) end
Add a transfer method for a builtin type
# File lib/syck.rb, line 324 def self.add_ruby_type( type_tag, &transfer_proc ) warn "#{caller[0]}: YAML.add_ruby_type is deprecated, use add_domain_type" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc ) end
Detect typing of a string
# File lib/syck.rb, line 340 def self.detect_implicit( val ) warn "#{caller[0]}: YAML.detect_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) resolver.detect_implicit( val ) 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"
# File lib/syck.rb, line 124 def self.dump( obj, io = nil ) obj.to_yaml( io || io2 = StringIO.new ) io || ( io2.rewind; io2.read ) end
Returns a YAML stream containing each of the items in objs
, each having their own document.
YAML.dump_stream( 0, [], {} ) #=> --- 0 --- [] --- {}
# File lib/syck.rb, line 299 def self.dump_stream( *objs ) d = Stream.new objs.each do |doc| d.add( doc ) end d.emit 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
# File lib/syck.rb, line 224 def self.each_document( io, &block ) warn "#{caller[0]}: YAML.each_document is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) parser.load_documents( io, &block ) 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
# File lib/syck.rb, line 255 def self.each_node( io, &doc_proc ) warn "#{caller[0]}: YAML.each_node is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) generic_parser.load_documents( io, &doc_proc ) end
Returns a new default emitter
# File lib/syck.rb, line 106 def self.emitter warn "#{caller[0]}: YAML.emitter is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) Emitter.new.set_resolver( self.resolver ) end
Escape the string, condensing common escapes
# File lib/syck/encoding.rb, line 10 def self.escape( value, skip = "" ) warn "#{caller[0]}: YAML.escape is deprecated" if $VERBOSE value.gsub( /\\/, "\\\\\\" ). gsub( /"/, "\\\"" ). gsub( /([\x00-\x1f])/ ) do skip[$&] || ESCAPES[ $&.unpack("C")[0] ] end end
Returns a new generic parser
# File lib/syck.rb, line 94 def self.generic_parser warn "#{caller[0]}: YAML.generic_parser is deprecated, switch to psych" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) 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
# File lib/syck.rb, line 140 def self.load( io ) parser.load( io ) 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
# File lib/syck.rb, line 240 def self.load_documents( io, &doc_proc ) parser.load_documents( io, &doc_proc ) end
Load a document from the file located at filepath.
YAML.load_file( 'animals.yaml' ) #=> ['badger', 'elephant', 'tiger']
# File lib/syck.rb, line 150 def self.load_file( filepath ) File.open( filepath ) do |f| load( f ) end end
Loads all documents from the current io stream, returning a YAML::Stream
object containing all loaded documents.
# File lib/syck.rb, line 281 def self.load_stream( io ) d = nil parser.load_documents( io ) do |doc| d = Stream.new if not d d.add( doc ) end return d end
Class
method for creating streams
# File lib/syck/stringio.rb, line 57 def Syck.make_stream( io ) if String === io io = StringIO.new( io ) elsif not IO === io raise Syck::Error, "YAML stream must be an IO or String object." end if Syck::unicode def io.readline Syck.utf_to_internal( readline( @ln_sep ), @utf_encoding ) end def io.check_unicode @utf_encoding = Syck.sniff_encoding( read( 4 ) ) @ln_sep = Syck.enc_separator( @utf_encoding ) seek( -4, IO::SEEK_CUR ) end def io.utf_encoding @utf_encoding end io.check_unicode else def io.utf_encoding :None end end io end
Allocate blank object
# File lib/syck.rb, line 383 def self.object_maker( obj_class, val ) warn "#{caller[0]}: YAML.object_maker is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) if Hash === val o = obj_class.allocate val.each_pair { |k,v| o.instance_variable_set("@#{k}", v) } o else raise Error, "Invalid object explicitly tagged !ruby/Object: " + val.inspect end 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>
# File lib/syck.rb, line 183 def self.parse( io ) generic_parser.load( io ) 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
# File lib/syck.rb, line 271 def self.parse_documents( io, &doc_proc ) warn "#{caller[0]}: YAML.parse_documents is deprecated, use load_stream" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) self.each_node( io, &doc_proc ) 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">]>
# File lib/syck.rb, line 207 def self.parse_file( filepath ) File.open( filepath ) do |f| parse( f ) end end
Returns a new default parser
# File lib/syck.rb, line 91 def self.parser; Parser.new.set_resolver( self.resolver ); end
Allocate an Emitter if needed
# File lib/syck.rb, line 399 def self.quick_emit( oid, opts = {}, &e ) warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) out = if opts.is_a? Emitter opts else emitter.reset( opts ) end out.emit( oid, &e ) end
Method to extract colon-separated type and class, returning the type and the constant of the class
# File lib/syck.rb, line 373 def self.read_type_class( type, obj_class ) warn "#{caller[0]}: YAML.read_type_class is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) type, tclass = type.split( ':', 4 ).last(2) tclass.split( "::" ).each { |c| obj_class = obj_class.const_get( c ) } if tclass return [ type, obj_class ] end
Returns the default resolver
# File lib/syck.rb, line 100 def self.resolver warn "#{caller[0]}: YAML.resolver is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) 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
# File lib/syck/tag.rb, line 34 def self.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
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
# File lib/syck/tag.rb, line 47 def self.tagged_classes @@tagged_classes end
Convert a type_id to a taguri
# File lib/syck.rb, line 348 def self.tagurize( val ) warn "#{caller[0]}: YAML.tagurize is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) resolver.tagurize( val ) end
Apply a transfer method to a Ruby object
# File lib/syck.rb, line 356 def self.transfer( type_id, obj ) warn "#{caller[0]}: YAML.transfer is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) resolver.transfer( tagurize( type_id ), obj ) end
Apply any implicit a node may qualify for
# File lib/syck.rb, line 364 def self.try_implicit( obj ) warn "#{caller[0]}: YAML.try_implicit is deprecated" if $VERBOSE && !caller[0].start_with?(File.dirname(__FILE__)) transfer( detect_implicit( obj ), obj ) end
Unescape the condenses escapes
# File lib/syck/encoding.rb, line 22 def self.unescape( value ) warn "#{caller[0]}: YAML.unescape is deprecated" if $VERBOSE value.gsub( /\\(?:([nevfbart\\])|0?x([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/ ) { if $3 ["#$3".hex ].pack('U*') elsif $2 [$2].pack( "H2" ) else UNESCAPES[$1] end } end