diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2012-03-08 13:23:08 -0800 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2012-03-08 13:23:08 -0800 |
commit | 34d3b22d2b94e58b0e51ac922ea48d686fcbb901 (patch) | |
tree | 7b9599abf65a350c7a680f15f4ccf0614674c2f9 | |
parent | 90acf338b14a31498e8888493b31a90f13978918 (diff) | |
download | psych-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.rdoc | 11 | ||||
-rw-r--r-- | lib/psych.rb | 40 | ||||
-rw-r--r-- | lib/psych/handlers/document_stream.rb | 22 | ||||
-rw-r--r-- | test/psych/test_stream.rb | 34 |
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) |