1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/yaml: Moved to ext/syck/lib, Syck only uses Syck constant.

* lib/yaml.rb: Added an engine manager for choosing YAML engine.
* ext/syck/lib/syck/rubytypes.rb: squashed warnings when using Psych

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27212 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
tenderlove 2010-04-03 21:50:47 +00:00
parent ca926ad017
commit eb71e5cd67
26 changed files with 645 additions and 530 deletions

View file

@ -1,3 +1,9 @@
Sun Apr 4 06:46:16 2010 Aaron Patterson <aaron@tenderlovemaking.com>
* lib/yaml: Moved to ext/syck/lib, Syck only uses Syck constant.
* lib/yaml.rb: Added an engine manager for choosing YAML engine.
* ext/syck/lib/syck/rubytypes.rb: squashed warnings when using Psych
Sat Apr 3 22:47:51 2010 Tanaka Akira <akr@fsij.org>
* time.c: don't define STRUCT_WIDEVAL.

456
ext/syck/lib/syck.rb Normal file
View file

@ -0,0 +1,456 @@
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
# $Id$
#
# = yaml.rb: top-level module with methods for loading and parsing YAML documents
#
# Author:: why the lucky stiff
#
require 'stringio'
require 'syck.so'
require 'syck/error'
require 'syck/syck'
require 'syck/tag'
require 'syck/stream'
require 'syck/constants'
# == 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 http://yaml.org/ for more information. For a quick tutorial, please
# visit YAML In Five Minutes (http://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 (http://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
#
module Syck
DefaultResolver.use_types_at( @@tagged_classes )
# Returns a new default parser
def self.parser; Parser.new.set_resolver( self.resolver ); end
# Returns a new generic parser
def self.generic_parser
warn "#{caller[0]}: YAML.generic_parser is deprecated, switch to psych" if $VERBOSE
Parser.new.set_resolver( GenericResolver )
end
# Returns the default resolver
def self.resolver
warn "#{caller[0]}: YAML.resolver is deprecated" if $VERBOSE
DefaultResolver
end
# Returns a new default emitter
def self.emitter
warn "#{caller[0]}: YAML.emitter is deprecated" if $VERBOSE
Emitter.new.set_resolver( self.resolver )
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"
#
def self.dump( obj, io = nil )
obj.to_yaml( io || io2 = StringIO.new )
io || ( io2.rewind; io2.read )
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
#
def self.load( io )
yp = parser.load( io )
end
#
# Load a document from the file located at _filepath_.
#
# YAML.load_file( 'animals.yaml' )
# #=> ['badger', 'elephant', 'tiger']
#
def self.load_file( filepath )
File.open( filepath ) do |f|
load( f )
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>
#
def self.parse( io )
yp = generic_parser.load( io )
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">]>
#
def self.parse_file( filepath )
File.open( filepath ) do |f|
parse( f )
end
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
#
def self.each_document( io, &block )
warn "#{caller[0]}: YAML.each_document is deprecated" if $VERBOSE
yp = parser.load_documents( io, &block )
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
#
def self.load_documents( io, &doc_proc )
yp = parser.load_documents( io, &doc_proc )
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
#
def self.each_node( io, &doc_proc )
warn "#{caller[0]}: YAML.each_node is deprecated" if $VERBOSE
yp = generic_parser.load_documents( io, &doc_proc )
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
#
def self.parse_documents( io, &doc_proc )
warn "#{caller[0]}: YAML.parse_documents is deprecated, use load_stream" if $VERBOSE
self.each_node( io, &doc_proc )
end
#
# Loads all documents from the current _io_ stream,
# returning a +YAML::Stream+ object containing all
# loaded documents.
#
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
#
# Returns a YAML stream containing each of the items in +objs+,
# each having their own document.
#
# YAML.dump_stream( 0, [], {} )
# #=> --- 0
# --- []
# --- {}
#
def self.dump_stream( *objs )
d = Stream.new
objs.each do |doc|
d.add( doc )
end
d.emit
end
#
# Add a global handler for a YAML domain type.
#
def self.add_domain_type( domain, type_tag, &transfer_proc )
resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
def self.add_builtin_type( type_tag, &transfer_proc )
resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
def self.add_ruby_type( type_tag, &transfer_proc )
warn "#{caller[0]}: YAML.add_ruby_type is deprecated, use add_domain_type" if $VERBOSE
resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
end
#
# Add a private document type
#
def self.add_private_type( type_re, &transfer_proc )
warn "#{caller[0]}: YAML.add_private_type is deprecated, use add_domain_type" if $VERBOSE
resolver.add_type( "x-private:" + type_re, transfer_proc )
end
#
# Detect typing of a string
#
def self.detect_implicit( val )
warn "#{caller[0]}: YAML.detect_implicit is deprecated" if $VERBOSE
resolver.detect_implicit( val )
end
#
# Convert a type_id to a taguri
#
def self.tagurize( val )
warn "#{caller[0]}: YAML.tagurize is deprecated" if $VERBOSE
resolver.tagurize( val )
end
#
# Apply a transfer method to a Ruby object
#
def self.transfer( type_id, obj )
warn "#{caller[0]}: YAML.transfer is deprecated" if $VERBOSE
resolver.transfer( tagurize( type_id ), obj )
end
#
# Apply any implicit a node may qualify for
#
def self.try_implicit( obj )
warn "#{caller[0]}: YAML.try_implicit is deprecated" if $VERBOSE
transfer( detect_implicit( obj ), obj )
end
#
# Method to extract colon-seperated type and class, returning
# the type and the constant of the class
#
def self.read_type_class( type, obj_class )
warn "#{caller[0]}: YAML.read_type_class is deprecated" if $VERBOSE
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
#
# Allocate blank object
#
def self.object_maker( obj_class, val )
warn "#{caller[0]}: YAML.object_maker is deprecated" if $VERBOSE
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
#
# Allocate an Emitter if needed
#
def self.quick_emit( oid, opts = {}, &e )
warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE
out =
if opts.is_a? Emitter
opts
else
emitter.reset( opts )
end
out.emit( oid, &e )
end
end
require 'syck/rubytypes'
require 'syck/types'
module Kernel
#
# ryan:: You know how Kernel.p is a really convenient way to dump ruby
# structures? The only downside is that it's not as legible as
# YAML.
#
# _why:: (listening)
#
# ryan:: I know you don't want to urinate all over your users' namespaces.
# But, on the other hand, convenience of dumping for debugging is,
# IMO, a big YAML use case.
#
# _why:: Go nuts! Have a pony parade!
#
# ryan:: Either way, I certainly will have a pony parade.
#
# Prints any supplied _objects_ out in YAML. Intended as
# a variation on +Kernel::p+.
#
# S = Struct.new(:name, :state)
# s = S['dave', 'TX']
# y s
#
# _produces:_
#
# --- !ruby/struct:S
# name: dave
# state: TX
#
def y( object, *objects )
objects.unshift object
puts( if objects.length == 1
YAML.dump( *objects )
else
YAML.dump_stream( *objects )
end )
end
private :y
end

View file

@ -2,15 +2,15 @@
# BaseEmitter
#
require 'yaml/constants'
require 'yaml/encoding'
require 'yaml/error'
require 'syck/constants'
require 'syck/encoding'
require 'syck/error'
module YAML
module Syck
module BaseEmitter
def options( opt = nil )
if opt
@options[opt] || YAML::DEFAULTS[opt]
@options[opt] || DEFAULTS[opt]
else
@options
end
@ -38,7 +38,7 @@ module YAML
block =
if options(:UseBlock)
'|'
elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{YAML::ESCAPE_CHAR}/
elsif not options(:UseFold) and valx =~ /\n[ \t]/ and not valx =~ /#{ESCAPE_CHAR}/
'|'
else
'>'
@ -61,7 +61,7 @@ module YAML
block += "\n"
if block[0] == ?"
esc_skip = ( "\t\n" unless valx =~ /^[ \t]/ ) || ""
valx = fold( YAML::escape( valx, esc_skip ) + "\"" ).chomp
valx = fold( Syck.escape( valx, esc_skip ) + "\"" ).chomp
self << '"' + indent_text( valx, indt, false )
else
if block[0] == ?>
@ -84,7 +84,7 @@ module YAML
# Emit double-quoted string
#
def double( value )
"\"#{YAML.escape( value )}\""
"\"#{Syck.escape( value )}\""
end
#

View file

@ -2,7 +2,7 @@
# YAML::BaseNode class
#
module YAML
module Syck
#
# YAML Generic Model container
@ -25,7 +25,7 @@ module YAML
matches.each { |m|
result.push m.last
}
YAML.transfer( 'seq', result )
Syck.transfer( 'seq', result )
end
end

View file

@ -1,7 +1,7 @@
#
# Constants used throughout the library
#
module YAML
module Syck
#
# Constants

View file

@ -1,10 +1,10 @@
require 'yaml'
require 'syck'
require 'dbm'
#
# YAML + DBM = YDBM
# - Same interface as DBM class
#
module YAML
module Syck
class DBM < ::DBM
VERSION = "0.1"
@ -17,7 +17,7 @@ class DBM < ::DBM
def fetch( keystr, ifnone = nil )
begin
val = super( keystr )
return YAML::load( val ) if String === val
return Syck.load( val ) if String === val
rescue IndexError
end
if block_given?
@ -35,7 +35,7 @@ class DBM < ::DBM
def delete( key )
v = super( key )
if String === v
v = YAML::load( v )
v = Syck.load( v )
end
v
end
@ -54,11 +54,11 @@ class DBM < ::DBM
self
end
def each_value
super { |v| yield YAML::load( v ) }
super { |v| yield Syck.load( v ) }
self
end
def values
super.collect { |v| YAML::load( v ) }
super.collect { |v| Syck.load( v ) }
end
def has_value?( val )
each_value { |v| return true if v == val }
@ -75,7 +75,7 @@ class DBM < ::DBM
end
def shift
a = super
a[1] = YAML::load( a[1] ) if a
a[1] = Syck.load( a[1] ) if a
a
end
def select( *keys )

View file

@ -2,12 +2,12 @@
# Handle Unicode-to-Internal conversion
#
module YAML
module Syck
#
# Escape the string, condensing common escapes
#
def YAML.escape( value, skip = "" )
def self.escape( value, skip = "" )
warn "#{caller[0]}: YAML.escape is deprecated" if $VERBOSE
value.gsub( /\\/, "\\\\\\" ).
gsub( /"/, "\\\"" ).
@ -19,7 +19,7 @@ module YAML
#
# Unescape the condenses escapes
#
def YAML.unescape( value )
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

View file

@ -2,7 +2,7 @@
# Error messages and exception class
#
module YAML
module Syck
#
# Error messages

View file

@ -2,7 +2,7 @@
# YAML::Loader class
# .. type handling ..
#
module YAML
module Syck
class Loader
TRANSFER_DOMAINS = {
'yaml.org,2002' => {},

View file

@ -20,6 +20,7 @@ class Object
end
end
end
alias :syck_to_yaml :to_yaml
end
class Hash
@ -35,6 +36,7 @@ class Hash
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
each do |k, v|
@ -83,6 +85,7 @@ class Struct
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
#
# Basic struct is passed as a YAML map
@ -104,6 +107,7 @@ class Array
yaml_as "tag:yaml.org,2002:seq"
def yaml_initialize( tag, val ); concat( val.to_a ); end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
each do |x|
@ -124,6 +128,7 @@ class Exception
o
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.map( taguri, to_yaml_style ) do |map|
map.add( 'message', message )
@ -161,6 +166,7 @@ class String
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( is_complex_yaml? ? self : nil, opts ) do |out|
if is_binary_data?
out.scalar( "tag:yaml.org,2002:binary", [self].pack("m"), :literal )
@ -190,6 +196,7 @@ class Symbol
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
out.scalar( "tag:yaml.org,2002:str", self.inspect, :plain )
end
@ -227,6 +234,7 @@ class Range
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
# if self.begin.is_complex_yaml? or self.begin.respond_to? :to_str or
# self.end.is_complex_yaml? or self.end.respond_to? :to_str or
@ -276,6 +284,7 @@ class Regexp
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
if to_yaml_properties.empty?
out.scalar( taguri, self.inspect, :plain )
@ -310,6 +319,7 @@ class Time
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
tz = "Z"
# from the tidy Tobias Peters <t-peters@gmx.de> Thanks!
@ -347,6 +357,7 @@ end
class Date
yaml_as "tag:yaml.org,2002:timestamp#ymd"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.scalar( "tag:yaml.org,2002:timestamp", self.to_s, :plain )
end
@ -356,6 +367,7 @@ end
class Integer
yaml_as "tag:yaml.org,2002:int"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
out.scalar( "tag:yaml.org,2002:int", self.to_s, :plain )
end
@ -365,6 +377,7 @@ end
class Float
yaml_as "tag:yaml.org,2002:float"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
str = self.to_s
if str == "Infinity"
@ -389,6 +402,7 @@ class Rational
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.map( taguri, nil ) do |map|
map.add( 'denominator', denominator )
@ -408,6 +422,7 @@ class Complex
end
end
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( self, opts ) do |out|
out.map( taguri, nil ) do |map|
map.add( 'image', imaginary )
@ -420,6 +435,7 @@ end
class TrueClass
yaml_as "tag:yaml.org,2002:bool#yes"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "true", :plain )
end
@ -429,6 +445,7 @@ end
class FalseClass
yaml_as "tag:yaml.org,2002:bool#no"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "false", :plain )
end
@ -438,6 +455,7 @@ end
class NilClass
yaml_as "tag:yaml.org,2002:null"
def to_yaml( opts = {} )
return super unless YAML::ENGINE.syck?
YAML::quick_emit( nil, opts ) do |out|
out.scalar( taguri, "", :plain )
end

View file

@ -1,12 +1,12 @@
#
# YAML::Store
#
require 'yaml'
require 'syck'
require 'pstore'
class YAML::Store < PStore
class Syck::Store < PStore
def initialize( *o )
@opt = YAML::DEFAULTS.dup
@opt = Syck::DEFAULTS.dup
if String === o.first
super(o.shift)
end
@ -20,7 +20,7 @@ class YAML::Store < PStore
end
def load(content)
table = YAML::load(content)
table = Syck::load(content)
if table == false
{}
else

View file

@ -1,4 +1,4 @@
module YAML
module Syck
#
# YAML::Stream -- for emitting many documents
@ -28,7 +28,7 @@ module YAML
def emit( io = nil )
# opts = @options.dup
# opts[:UseHeader] = true if @documents.length > 1
out = YAML.emitter
out = Syck.emitter
out.reset( io || io2 = StringIO.new )
@documents.each { |v|
v.to_yaml( out )

View file

@ -54,19 +54,19 @@ rescue LoadError
#
# Class method for creating streams
#
def YAML.make_stream( io )
def Syck.make_stream( io )
if String === io
io = StringIO.new( io )
elsif not IO === io
raise YAML::Error, "YAML stream must be an IO or String object."
raise Syck::Error, "YAML stream must be an IO or String object."
end
if YAML::unicode
if Syck::unicode
def io.readline
YAML.utf_to_internal( readline( @ln_sep ), @utf_encoding )
Syck.utf_to_internal( readline( @ln_sep ), @utf_encoding )
end
def io.check_unicode
@utf_encoding = YAML.sniff_encoding( read( 4 ) )
@ln_sep = YAML.enc_separator( @utf_encoding )
@utf_encoding = Syck.sniff_encoding( read( 4 ) )
@ln_sep = Syck.enc_separator( @utf_encoding )
seek( -4, IO::SEEK_CUR )
end
def io.utf_encoding

17
ext/syck/lib/syck/syck.rb Normal file
View file

@ -0,0 +1,17 @@
#
# YAML::Syck module
# .. glues syck and yaml.rb together ..
#
require 'syck'
require 'syck/basenode'
module Syck
#
# Mixin BaseNode functionality
#
class Node
include Syck::BaseNode
end
end

View file

@ -5,7 +5,7 @@
#
# Author:: why the lucky stiff
#
module YAML
module Syck
# A dictionary of taguris which map to
# Ruby classes.
@@tagged_classes = {}
@ -32,7 +32,7 @@ module YAML
#
# tag:why@ruby-lang.org,2004:notes/personal
#
def YAML.tag_class( tag, cls )
def self.tag_class( tag, cls )
if @@tagged_classes.has_key? tag
warn "class #{ @@tagged_classes[tag] } held ownership of the #{ tag } tag"
end
@ -45,7 +45,7 @@ module YAML
#
# YAML.tagged_classes["tag:yaml.org,2002:int"] => Integer
#
def YAML.tagged_classes
def self.tagged_classes
@@tagged_classes
end
end
@ -62,11 +62,11 @@ class Module
attr_writer :taguri
def taguri
if respond_to? :to_yaml_type
YAML::tagurize( to_yaml_type[1..-1] )
Syck.tagurize( to_yaml_type[1..-1] )
else
return @taguri if defined?(@taguri) and @taguri
tag = #{ tag.dump }
if self.class.yaml_tag_subclasses? and self.class != YAML::tagged_classes[tag]
if self.class.yaml_tag_subclasses? and self.class != Syck.tagged_classes[tag]
tag = "\#{ tag }:\#{ self.class.yaml_tag_class_name }"
end
tag
@ -74,7 +74,7 @@ class Module
end
def self.yaml_tag_subclasses?; #{ sc ? 'true' : 'false' }; end
END
YAML::tag_class tag, self
Syck.tag_class tag, self
ensure
$VERBOSE = verbose
end

View file

@ -3,7 +3,7 @@
# Classes required by the full core typeset
#
module YAML
module Syck
#
# Default private type
@ -45,7 +45,7 @@ module YAML
class Object
def self.tag_subclasses?; false; end
def to_yaml( opts = {} )
YAML::quick_emit( self, opts ) do |out|
Syck.quick_emit( self, opts ) do |out|
out.map( "tag:ruby.yaml.org,2002:object:#{ @class }", to_yaml_style ) do |map|
@ivars.each do |k,v|
map.add( k, v )
@ -67,7 +67,7 @@ module YAML
self.default.to_s
end
def update( h )
if YAML::SpecialHash === h
if Syck::SpecialHash === h
@default = h.default if h.default
end
super( h )
@ -89,11 +89,11 @@ module YAML
if Hash === v
concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !omap entry: " + val.inspect
raise Syck::Error, "Invalid !omap entry: " + val.inspect
end
end
else
raise YAML::Error, "Invalid !omap: " + val.inspect
raise Syck::Error, "Invalid !omap: " + val.inspect
end
self
end
@ -123,7 +123,7 @@ module YAML
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self, opts ) do |out|
Syck.quick_emit( self, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )
@ -144,11 +144,11 @@ module YAML
if Hash === v
concat( v.to_a ) # Convert the map to a sequence
else
raise YAML::Error, "Invalid !pairs entry: " + val.inspect
raise Syck::Error, "Invalid !pairs entry: " + val.inspect
end
end
else
raise YAML::Error, "Invalid !pairs: " + val.inspect
raise Syck::Error, "Invalid !pairs: " + val.inspect
end
self
end
@ -173,7 +173,7 @@ module YAML
true
end
def to_yaml( opts = {} )
YAML::quick_emit( self, opts ) do |out|
Syck.quick_emit( self, opts ) do |out|
out.seq( taguri, to_yaml_style ) do |seq|
self.each do |v|
seq.add( Hash[ *v ] )

View file

@ -1,9 +1,9 @@
#
# YAML::YamlNode class
#
require 'yaml/basenode'
require 'syck/basenode'
module YAML
module Syck
#
# YAML Generic Model container
@ -46,7 +46,7 @@ module YAML
else
t = @value
end
YAML.transfer_method( @type_id, t )
Syck.transfer_method( @type_id, t )
end
end

View file

@ -4,7 +4,7 @@
warn "#{caller[0]}: YAML::YPath is deprecated" if $VERBOSE
module YAML
module Syck
class YPath
attr_accessor :segments, :predicates, :flags
@ -24,7 +24,7 @@ module YAML
@segments.push "."
end
end
def YPath.each_path( str )
def self.each_path( str )
#
# Find choices
#

View file

@ -2111,9 +2111,7 @@ syck_out_scalar(int argc, VALUE *argv, VALUE self)
void
Init_syck()
{
VALUE rb_yaml = rb_define_module( "YAML" );
VALUE rb_syck = rb_define_module_under( rb_yaml, "Syck" );
rb_define_const( rb_syck, "VERSION", rb_str_new2( SYCK_VERSION ) );
VALUE rb_syck = rb_define_module_under( rb_cObject, "Syck" );
rb_define_module_function( rb_syck, "compile", rb_syck_compile, 1 );
/*
@ -2258,7 +2256,7 @@ Init_syck()
/*
* Define YAML::PrivateType class
*/
cPrivateType = rb_define_class_under( rb_yaml, "PrivateType", rb_cObject );
cPrivateType = rb_define_class_under( rb_syck, "PrivateType", rb_cObject );
rb_define_attr( cPrivateType, "type_id", 1, 1 );
rb_define_attr( cPrivateType, "value", 1, 1 );
rb_define_method( cPrivateType, "initialize", syck_privatetype_initialize, 2);
@ -2266,7 +2264,7 @@ Init_syck()
/*
* Define YAML::DomainType class
*/
cDomainType = rb_define_class_under( rb_yaml, "DomainType", rb_cObject );
cDomainType = rb_define_class_under( rb_syck, "DomainType", rb_cObject );
rb_define_attr( cDomainType, "domain", 1, 1 );
rb_define_attr( cDomainType, "type_id", 1, 1 );
rb_define_attr( cDomainType, "value", 1, 1 );
@ -2275,7 +2273,7 @@ Init_syck()
/*
* Define YAML::Object class
*/
cYObject = rb_define_class_under( rb_yaml, "Object", rb_cObject );
cYObject = rb_define_class_under( rb_syck, "Object", rb_cObject );
rb_define_attr( cYObject, "class", 1, 1 );
rb_define_attr( cYObject, "ivars", 1, 1 );
rb_define_method( cYObject, "initialize", syck_yobject_initialize, 2);

View file

@ -12,7 +12,6 @@
#define SYCK_YAML_MAJOR 1
#define SYCK_YAML_MINOR 0
#define SYCK_VERSION "0.60"
#define YAML_DOMAIN "yaml.org,2002"
#include <stdio.h>

View file

@ -1,460 +1,40 @@
# -*- mode: ruby; ruby-indent-level: 4; tab-width: 4 -*- vim: sw=4 ts=4
# $Id$
#
# = yaml.rb: top-level module with methods for loading and parsing YAML documents
#
# Author:: why the lucky stiff
#
require 'stringio'
require 'yaml/error'
require 'yaml/syck'
require 'yaml/tag'
require 'yaml/stream'
require 'yaml/constants'
# == 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 http://yaml.org/ for more information. For a quick tutorial, please
# visit YAML In Five Minutes (http://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 (http://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
#
module YAML
class EngineManager # :nodoc:
attr_reader :yamler
Resolver = YAML::Syck::Resolver
DefaultResolver = YAML::Syck::DefaultResolver
DefaultResolver.use_types_at( @@tagged_classes )
GenericResolver = YAML::Syck::GenericResolver
Parser = YAML::Syck::Parser
Emitter = YAML::Syck::Emitter
# Returns a new default parser
def YAML.parser; Parser.new.set_resolver( YAML.resolver ); end
# Returns a new generic parser
def YAML.generic_parser
warn "#{caller[0]}: YAML.generic_parser is deprecated, switch to psych" if $VERBOSE
Parser.new.set_resolver( GenericResolver )
def initialize
@yamler = nil
end
# Returns the default resolver
def YAML.resolver
warn "#{caller[0]}: YAML.resolver is deprecated" if $VERBOSE
DefaultResolver
def syck?
'syck' == @yamler
end
# Returns a new default emitter
def YAML.emitter
warn "#{caller[0]}: YAML.emitter is deprecated" if $VERBOSE
Emitter.new.set_resolver( YAML.resolver )
def yamler= engine
raise(ArgumentError, "bad engine") unless %w{syck psych}.include?(engine)
@yamler = engine
require engine
Object.class_eval <<-eorb, __FILE__, __LINE__ + 1
remove_const 'YAML'
YAML = #{engine.capitalize}
remove_method :to_yaml
alias :to_yaml :#{engine}_to_yaml
eorb
engine
end
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"
#
def YAML.dump( obj, io = nil )
obj.to_yaml( io || io2 = StringIO.new )
io || ( io2.rewind; io2.read )
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
#
def YAML.load( io )
yp = parser.load( io )
end
#
# Load a document from the file located at _filepath_.
#
# YAML.load_file( 'animals.yaml' )
# #=> ['badger', 'elephant', 'tiger']
#
def YAML.load_file( filepath )
File.open( filepath ) do |f|
load( f )
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>
#
def YAML.parse( io )
yp = generic_parser.load( io )
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">]>
#
def YAML.parse_file( filepath )
File.open( filepath ) do |f|
parse( f )
end
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
#
def YAML.each_document( io, &block )
warn "#{caller[0]}: YAML.each_document is deprecated" if $VERBOSE
yp = parser.load_documents( io, &block )
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
#
def YAML.load_documents( io, &doc_proc )
yp = parser.load_documents( io, &doc_proc )
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
#
def YAML.each_node( io, &doc_proc )
warn "#{caller[0]}: YAML.each_node is deprecated" if $VERBOSE
yp = generic_parser.load_documents( io, &doc_proc )
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
#
def YAML.parse_documents( io, &doc_proc )
warn "#{caller[0]}: YAML.parse_documents is deprecated, use load_stream" if $VERBOSE
YAML.each_node( io, &doc_proc )
end
#
# Loads all documents from the current _io_ stream,
# returning a +YAML::Stream+ object containing all
# loaded documents.
#
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
#
# Returns a YAML stream containing each of the items in +objs+,
# each having their own document.
#
# YAML.dump_stream( 0, [], {} )
# #=> --- 0
# --- []
# --- {}
#
def YAML.dump_stream( *objs )
d = YAML::Stream.new
objs.each do |doc|
d.add( doc )
end
d.emit
end
#
# Add a global handler for a YAML domain type.
#
def YAML.add_domain_type( domain, type_tag, &transfer_proc )
resolver.add_type( "tag:#{ domain }:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
def YAML.add_builtin_type( type_tag, &transfer_proc )
resolver.add_type( "tag:yaml.org,2002:#{ type_tag }", transfer_proc )
end
#
# Add a transfer method for a builtin type
#
def YAML.add_ruby_type( type_tag, &transfer_proc )
warn "#{caller[0]}: YAML.add_ruby_type is deprecated, use add_domain_type" if $VERBOSE
resolver.add_type( "tag:ruby.yaml.org,2002:#{ type_tag }", transfer_proc )
end
#
# Add a private document type
#
def YAML.add_private_type( type_re, &transfer_proc )
warn "#{caller[0]}: YAML.add_private_type is deprecated, use add_domain_type" if $VERBOSE
resolver.add_type( "x-private:" + type_re, transfer_proc )
end
#
# Detect typing of a string
#
def YAML.detect_implicit( val )
warn "#{caller[0]}: YAML.detect_implicit is deprecated" if $VERBOSE
resolver.detect_implicit( val )
end
#
# Convert a type_id to a taguri
#
def YAML.tagurize( val )
warn "#{caller[0]}: YAML.tagurize is deprecated" if $VERBOSE
resolver.tagurize( val )
end
#
# Apply a transfer method to a Ruby object
#
def YAML.transfer( type_id, obj )
warn "#{caller[0]}: YAML.transfer is deprecated" if $VERBOSE
resolver.transfer( YAML.tagurize( type_id ), obj )
end
#
# Apply any implicit a node may qualify for
#
def YAML.try_implicit( obj )
warn "#{caller[0]}: YAML.try_implicit is deprecated" if $VERBOSE
YAML.transfer( YAML.detect_implicit( obj ), obj )
end
#
# Method to extract colon-seperated type and class, returning
# the type and the constant of the class
#
def YAML.read_type_class( type, obj_class )
warn "#{caller[0]}: YAML.read_type_class is deprecated" if $VERBOSE
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
#
# Allocate blank object
#
def YAML.object_maker( obj_class, val )
warn "#{caller[0]}: YAML.object_maker is deprecated" if $VERBOSE
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
#
# Allocate an Emitter if needed
#
def YAML.quick_emit( oid, opts = {}, &e )
warn "#{caller[0]}: YAML.quick_emit is deprecated" if $VERBOSE
out =
if opts.is_a? YAML::Emitter
opts
else
emitter.reset( opts )
end
out.emit( oid, &e )
end
ENGINE = YAML::EngineManager.new
end
require 'yaml/rubytypes'
require 'yaml/types'
module Kernel
#
# ryan:: You know how Kernel.p is a really convenient way to dump ruby
# structures? The only downside is that it's not as legible as
# YAML.
#
# _why:: (listening)
#
# ryan:: I know you don't want to urinate all over your users' namespaces.
# But, on the other hand, convenience of dumping for debugging is,
# IMO, a big YAML use case.
#
# _why:: Go nuts! Have a pony parade!
#
# ryan:: Either way, I certainly will have a pony parade.
#
# Prints any supplied _objects_ out in YAML. Intended as
# a variation on +Kernel::p+.
#
# S = Struct.new(:name, :state)
# s = S['dave', 'TX']
# y s
#
# _produces:_
#
# --- !ruby/struct:S
# name: dave
# state: TX
#
def y( object, *objects )
objects.unshift object
puts( if objects.length == 1
YAML::dump( *objects )
else
YAML::dump_stream( *objects )
end )
end
private :y
module Syck
ENGINE = YAML::ENGINE
end
module Psych
ENGINE = YAML::ENGINE
end
YAML::ENGINE.yamler = 'syck'

View file

@ -1,19 +0,0 @@
#
# YAML::Syck module
# .. glues syck and yaml.rb together ..
#
require 'syck'
require 'yaml/basenode'
module YAML
module Syck
#
# Mixin BaseNode functionality
#
class Node
include YAML::BaseNode
end
end
end

View file

@ -0,0 +1,57 @@
require_relative 'helper'
require 'yaml'
module Psych
class TestEngineManager < TestCase
def teardown
YAML::ENGINE.yamler = 'syck'
end
def test_bad_engine
assert_raises(ArgumentError) do
YAML::ENGINE.yamler = 'foooo'
end
end
def test_set_psych
YAML::ENGINE.yamler = 'psych'
assert_equal Psych, YAML
assert_equal 'psych', YAML::ENGINE.yamler
end
def test_set_syck
YAML::ENGINE.yamler = 'syck'
assert_equal Syck, YAML
assert_equal 'syck', YAML::ENGINE.yamler
end
A = Struct.new(:name)
def test_dump_types
YAML::ENGINE.yamler = 'psych'
assert_to_yaml ::Object.new
assert_to_yaml Time.now
assert_to_yaml Date.today
assert_to_yaml('a' => 'b')
assert_to_yaml A.new('foo')
assert_to_yaml %w{a b}
assert_to_yaml Exception.new('foo')
assert_to_yaml "hello!"
assert_to_yaml :fooo
assert_to_yaml(1..10)
assert_to_yaml(/hello!~/)
assert_to_yaml 1
assert_to_yaml 1.2
assert_to_yaml Rational(1, 2)
assert_to_yaml Complex(1, 2)
assert_to_yaml true
assert_to_yaml false
assert_to_yaml nil
end
def assert_to_yaml obj
assert obj.to_yaml, "#{obj.class} to_yaml works"
end
end
end

View file

@ -0,0 +1,3 @@
require 'test/unit'
require 'yaml'

View file

@ -4,7 +4,7 @@
#
require 'test/unit'
require 'yaml'
require 'yaml/ypath'
require 'syck/ypath'
# [ruby-core:01946]
module YAML_Tests

View file

@ -1,5 +1,5 @@
require 'test/unit'
require 'yaml/store'
require 'syck/store'
class YAMLStoreTest < Test::Unit::TestCase
def setup