diff --git a/lib/open3.rb b/lib/open3.rb
index 5ff1012..ef0cdcd 100644
--- a/lib/open3.rb
+++ b/lib/open3.rb
@@ -223,6 +223,7 @@ class << self
# opts[:stdin_data]
and opts[:binmode]
. See Process.spawn.
#
# If opts[:stdin_data]
is specified, it is sent to the command's standard input.
+ # It can be given as a String or an IO.
#
# If opts[:binmode]
is true, internal pipes are set to binary mode.
#
@@ -248,13 +249,13 @@ class << self
# # But if the image is stored in a DB or generated by the gnuplot Open3.capture2 example,
# # Open3.capture3 should be considered.
# #
- # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true)
+ # image = File.open("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true)
# thumbnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true)
# if s.success?
# STDOUT.binmode; print thumbnail
# end
#
- def capture3(*cmd, stdin_data: '', binmode: false, **opts)
+ def capture3(*cmd, stdin_data: nil, binmode: false, **opts)
popen3(*cmd, opts) {|i, o, e, t|
if binmode
i.binmode
@@ -263,9 +264,15 @@ def capture3(*cmd, stdin_data: '', binmode: false, **opts)
end
out_reader = Thread.new { o.read }
err_reader = Thread.new { e.read }
- begin
- i.write stdin_data
- rescue Errno::EPIPE
+ if stdin_data
+ begin
+ if stdin_data.respond_to?(:read)
+ IO.copy_stream(stdin_data, i)
+ else
+ i.write stdin_data
+ end
+ rescue Errno::EPIPE
+ end
end
i.close
[out_reader.value, err_reader.value, t.value]
@@ -281,6 +288,7 @@ def capture3(*cmd, stdin_data: '', binmode: false, **opts)
# opts[:stdin_data]
and opts[:binmode]
. See Process.spawn.
#
# If opts[:stdin_data]
is specified, it is sent to the command's standard input.
+ # It can be given as a String or an IO.
#
# If opts[:binmode]
is true, internal pipes are set to binary mode.
#
@@ -311,7 +319,11 @@ def capture2(*cmd, stdin_data: nil, binmode: false, **opts)
out_reader = Thread.new { o.read }
if stdin_data
begin
- i.write stdin_data
+ if stdin_data.respond_to?(:read)
+ IO.copy_stream(stdin_data, i)
+ else
+ i.write stdin_data
+ end
rescue Errno::EPIPE
end
end
@@ -329,6 +341,7 @@ def capture2(*cmd, stdin_data: nil, binmode: false, **opts)
# opts[:stdin_data]
and opts[:binmode]
. See Process.spawn.
#
# If opts[:stdin_data]
is specified, it is sent to the command's standard input.
+ # It can be given as a String or an IO.
#
# If opts[:binmode]
is true, internal pipes are set to binary mode.
#
@@ -346,7 +359,11 @@ def capture2e(*cmd, stdin_data: nil, binmode: false, **opts)
outerr_reader = Thread.new { oe.read }
if stdin_data
begin
- i.write stdin_data
+ if stdin_data.respond_to?(:read)
+ IO.copy_stream(stdin_data, i)
+ else
+ i.write stdin_data
+ end
rescue Errno::EPIPE
end
end
diff --git a/test/test_open3.rb b/test/test_open3.rb
index d52ab6a..0015c57 100644
--- a/test/test_open3.rb
+++ b/test/test_open3.rb
@@ -2,6 +2,7 @@
require 'test/unit'
require 'open3'
+require 'stringio'
class TestOpen3 < Test::Unit::TestCase
RUBY = EnvUtil.rubybin
@@ -162,32 +163,70 @@ def test_capture3_flip
assert(s.success?)
end
+ def test_capture3_stdin_string
+ o, e, s = Open3.capture3(RUBY, '-e', 'print STDIN.read', :stdin_data=>"z"*(1024*1024))
+ assert_equal("z"*(1024*1024), o)
+ assert_equal("", e)
+ assert(s.success?)
+ end
+
+ def test_capture3_stdin_io
+ o, e, s = Open3.capture3(RUBY, '-e', 'print STDIN.read', :stdin_data=>StringIO.new("z"*(1024*1024)))
+ assert_equal("z"*(1024*1024), o)
+ assert_equal("", e)
+ assert(s.success?)
+ end
+
+ def test_capture3_stdin_closed
+ o, e, s = Open3.capture3(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
+ assert_equal("", o)
+ assert_equal("", e)
+ assert(s.success?)
+ end
+
def test_capture2
o, s = Open3.capture2(RUBY, '-e', 'i=STDIN.read; print i+"o"', :stdin_data=>"i")
assert_equal("io", o)
assert(s.success?)
end
+ def test_capture2_stdin_string
+ o, s = Open3.capture2(RUBY, '-e', 'print STDIN.read', :stdin_data=>"z"*(1024*1024))
+ assert_equal("z"*(1024*1024), o)
+ assert(s.success?)
+ end
+
+ def test_capture2_stdin_io
+ o, s = Open3.capture2(RUBY, '-e', 'print STDIN.read', :stdin_data=>StringIO.new("z"*(1024*1024)))
+ assert_equal("z"*(1024*1024), o)
+ assert(s.success?)
+ end
+
+ def test_capture2_stdin_closed
+ o, s = Open3.capture2(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
+ assert_equal("", o)
+ assert(s.success?)
+ end
+
def test_capture2e
oe, s = Open3.capture2e(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>"i")
assert_equal("ioie", oe)
assert(s.success?)
end
- def test_capture3_stdin_data
- o, e, s = Open3.capture3(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
- assert_equal("", o)
- assert_equal("", e)
+ def test_capture2e_stdin_string
+ oe, s = Open3.capture2e(RUBY, '-e', 'print STDIN.read', :stdin_data=>"z"*(1024*1024))
+ assert_equal("z"*(1024*1024), oe)
assert(s.success?)
end
- def test_capture2_stdin_data
- o, s = Open3.capture2(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
- assert_equal("", o)
+ def test_capture2e_stdin_io
+ oe, s = Open3.capture2e(RUBY, '-e', 'print STDIN.read', :stdin_data=>StringIO.new("z"*(1024*1024)))
+ assert_equal("z"*(1024*1024), oe)
assert(s.success?)
end
- def test_capture2e_stdin_data
+ def test_capture2e_stdin_closed
oe, s = Open3.capture2e(RUBY, '-e', '', :stdin_data=>"z"*(1024*1024))
assert_equal("", oe)
assert(s.success?)