Permalink
Browse files

* 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.
  • Loading branch information...
1 parent 90acf33 commit 34d3b22d2b94e58b0e51ac922ea48d686fcbb901 @tenderlove tenderlove committed Mar 8, 2012
Showing with 101 additions and 6 deletions.
  1. +11 −0 CHANGELOG.rdoc
  2. +34 −6 lib/psych.rb
  3. +22 −0 lib/psych/handlers/document_stream.rb
  4. +34 −0 test/psych/test_stream.rb
View
@@ -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
View
@@ -13,6 +13,7 @@
require 'psych/stream'
require 'psych/json/tree_builder'
require 'psych/json/stream'
+require 'psych/handlers/document_stream'
###
# = Overview
@@ -173,12 +174,19 @@ def self.parser
# +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 @@ def self.parser
# 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 @@ def self.to_json o
###
# 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
###
@@ -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
View
@@ -2,6 +2,40 @@
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)

0 comments on commit 34d3b22

Please sign in to comment.