summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2012-03-08 13:23:08 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2012-03-08 13:23:08 -0800
commit34d3b22d2b94e58b0e51ac922ea48d686fcbb901 (patch)
tree7b9599abf65a350c7a680f15f4ccf0614674c2f9
parent90acf338b14a31498e8888493b31a90f13978918 (diff)
downloadpsych-34d3b22d2b94e58b0e51ac922ea48d686fcbb901.zip
* ext/psych/lib/psych.rb (parse_stream, load_stream): if a block is
given, documents will be yielded to the block as they are parsed. [ruby-core:42404] [Bug #5978] * ext/psych/lib/psych/handlers/document_stream.rb: add a handler that yields documents as they are parsed * test/psych/test_stream.rb: corresponding tests.
-rw-r--r--CHANGELOG.rdoc11
-rw-r--r--lib/psych.rb40
-rw-r--r--lib/psych/handlers/document_stream.rb22
-rw-r--r--test/psych/test_stream.rb34
4 files changed, 101 insertions, 6 deletions
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc
index 599fbed..9f8fcd5 100644
--- a/CHANGELOG.rdoc
+++ b/CHANGELOG.rdoc
@@ -1,3 +1,14 @@
+Fri Mar 9 06:17:05 2012 Aaron Patterson <aaron@tenderlovemaking.com>
+
+ * ext/psych/lib/psych.rb (parse_stream, load_stream): if a block is
+ given, documents will be yielded to the block as they are parsed.
+ [ruby-core:42404] [Bug #5978]
+
+ * ext/psych/lib/psych/handlers/document_stream.rb: add a handler that
+ yields documents as they are parsed
+
+ * test/psych/test_stream.rb: corresponding tests.
+
Tue Mar 6 02:31:20 2012 Aaron Patterson <aaron@tenderlovemaking.com>
* ext/psych/lib/psych/core_ext.rb: only extend Kernel if IRB is loaded
diff --git a/lib/psych.rb b/lib/psych.rb
index cb5c4a5..69f3a7c 100644
--- a/lib/psych.rb
+++ b/lib/psych.rb
@@ -13,6 +13,7 @@ require 'psych/deprecated'
require 'psych/stream'
require 'psych/json/tree_builder'
require 'psych/json/stream'
+require 'psych/handlers/document_stream'
###
# = Overview
@@ -173,12 +174,19 @@ module Psych
# +filename+ is used in the exception message if a Psych::SyntaxError is
# raised.
#
+ # If a block is given, a Psych::Nodes::Document node will be yielded to the
+ # block as it's being parsed.
+ #
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
# Example:
#
# Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00>
#
+ # Psych.parse_stream("--- a\n--- b") do |node|
+ # node # => #<Psych::Nodes::Document:0x00>
+ # end
+ #
# begin
# Psych.parse_stream("--- `", "file.txt")
# rescue Psych::SyntaxError => ex
@@ -187,10 +195,15 @@ module Psych
# end
#
# See Psych::Nodes for more information about YAML AST.
- def self.parse_stream yaml, filename = nil
- parser = self.parser
- parser.parse yaml, filename
- parser.handler.root
+ def self.parse_stream yaml, filename = nil, &block
+ if block_given?
+ parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
+ parser.parse yaml, filename
+ else
+ parser = self.parser
+ parser.parse yaml, filename
+ parser.handler.root
+ end
end
###
@@ -252,12 +265,27 @@ module Psych
###
# Load multiple documents given in +yaml+. Returns the parsed documents
- # as a list. For example:
+ # as a list. If a block is given, each document will be converted to ruby
+ # and passed to the block during parsing
+ #
+ # Example:
#
# Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
#
+ # list = []
+ # Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby|
+ # list << ruby
+ # end
+ # list # => ['foo', 'bar']
+ #
def self.load_stream yaml, filename = nil
- parse_stream(yaml, filename).children.map { |child| child.to_ruby }
+ if block_given?
+ parse_stream(yaml, filename) do |node|
+ yield node.to_ruby
+ end
+ else
+ parse_stream(yaml, filename).children.map { |child| child.to_ruby }
+ end
end
###
diff --git a/lib/psych/handlers/document_stream.rb b/lib/psych/handlers/document_stream.rb
new file mode 100644
index 0000000..e429993
--- /dev/null
+++ b/lib/psych/handlers/document_stream.rb
@@ -0,0 +1,22 @@
+require 'psych/tree_builder'
+
+module Psych
+ module Handlers
+ class DocumentStream < Psych::TreeBuilder # :nodoc:
+ def initialize &block
+ super
+ @block = block
+ end
+
+ def start_document version, tag_directives, implicit
+ n = Nodes::Document.new version, tag_directives, implicit
+ push n
+ end
+
+ def end_document implicit_end = !streaming?
+ @last.implicit_end = implicit_end
+ @block.call pop
+ end
+ end
+ end
+end
diff --git a/test/psych/test_stream.rb b/test/psych/test_stream.rb
index 4d8f137..9807207 100644
--- a/test/psych/test_stream.rb
+++ b/test/psych/test_stream.rb
@@ -2,6 +2,40 @@ require 'psych/helper'
module Psych
class TestStream < TestCase
+ def test_parse_stream_yields_documents
+ list = []
+ Psych.parse_stream("--- foo\n...\n--- bar") do |doc|
+ list << doc.to_ruby
+ end
+ assert_equal %w{ foo bar }, list
+ end
+
+ def test_parse_stream_break
+ list = []
+ Psych.parse_stream("--- foo\n...\n--- `") do |doc|
+ list << doc.to_ruby
+ break
+ end
+ assert_equal %w{ foo }, list
+ end
+
+ def test_load_stream_yields_documents
+ list = []
+ Psych.load_stream("--- foo\n...\n--- bar") do |ruby|
+ list << ruby
+ end
+ assert_equal %w{ foo bar }, list
+ end
+
+ def test_load_stream_break
+ list = []
+ Psych.load_stream("--- foo\n...\n--- `") do |ruby|
+ list << ruby
+ break
+ end
+ assert_equal %w{ foo }, list
+ end
+
def test_explicit_documents
io = StringIO.new
stream = Psych::Stream.new(io)