[前][次][番号順一覧][スレッド一覧]

ruby-changes:9008

From: akr <ko1@a...>
Date: Fri, 5 Dec 2008 19:07:27 +0900 (JST)
Subject: [ruby-changes:9008] Ruby:r20544 (trunk): * lib/open3.rb (Open3.pipeline_start): new method.

akr	2008-12-05 19:07:13 +0900 (Fri, 05 Dec 2008)

  New Revision: 20544

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20544

  Log:
    * lib/open3.rb (Open3.pipeline_start): new method.
      (Open3.pipeline): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/lib/open3.rb
    trunk/test/test_open3.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 20543)
+++ ChangeLog	(revision 20544)
@@ -1,3 +1,8 @@
+Fri Dec  5 19:06:04 2008  Tanaka Akira  <akr@f...>
+
+	* lib/open3.rb (Open3.pipeline_start): new method.
+	  (Open3.pipeline): ditto.
+
 Fri Dec  5 18:55:25 2008  Tanaka Akira  <akr@f...>
 
 	* process.c (run_exec_dup2): !save is false if Qnil.
Index: lib/open3.rb
===================================================================
--- lib/open3.rb	(revision 20543)
+++ lib/open3.rb	(revision 20544)
@@ -18,9 +18,11 @@
 # - Open3.poutput3 : give a string for stdin.  get strings for stdout, stderr
 # - Open3.poutput2 : give a string for stdin.  get a string for stdout
 # - Open3.poutput2e : give a string for stdin.  get a string for merged stdout and stderr
-# - Open3.pipeline_rw : pipes for stdin of the first and stdout of the last of a pipeline
-# - Open3.pipeline_r : pipe for stdout of the last of a pipeline
-# - Open3.pipeline_w : pipe for stdin of the first of a pipeline
+# - Open3.pipeline_rw : pipes for first stdin and last stdout of a pipeline
+# - Open3.pipeline_r : pipe for last stdout of a pipeline
+# - Open3.pipeline_w : pipe for first stdin of a pipeline
+# - Open3.pipeline_start : a pipeline
+# - Open3.pipeline : run a pipline and wait
 #
 
 module Open3
@@ -74,14 +76,14 @@
     end
 
     in_r, in_w = IO.pipe
-    opts[STDIN] = in_r
+    opts[:in] = in_r
     in_w.sync = true
 
     out_r, out_w = IO.pipe
-    opts[STDOUT] = out_w
+    opts[:out] = out_w
 
     err_r, err_w = IO.pipe
-    opts[STDERR] = err_w
+    opts[:err] = err_w
 
     popen_run(cmd, opts, [in_r, out_w, err_w], [in_w, out_r, err_r], &block)
   end
@@ -105,6 +107,26 @@
   #   stdin.close  # stdin and stdout should be closed explicitly in this form.
   #   stdout.close
   #
+  # Example:
+  #
+  #   Open3.popen2("wc -c") {|i,o,t|
+  #     i.print "answer to life the universe and everything"
+  #     i.close
+  #     p o.gets #=> "42\n"
+  #   }
+  #
+  #   Open3.popen2("bc -q") {|i,o,t| 
+  #     i.puts "obase=13"
+  #     i.puts "6 * 9"
+  #     p o.gets #=> "42\n"
+  #   }
+  #
+  #   Open3.popen2("dc") {|i,o,t|
+  #     i.print "42P"                                       
+  #     i.close
+  #     p o.read #=> "*"
+  #   }
+  #
   def popen2(*cmd, &block)
     if Hash === cmd.last
       opts = cmd.pop.dup
@@ -113,11 +135,11 @@
     end
 
     in_r, in_w = IO.pipe
-    opts[STDIN] = in_r
+    opts[:in] = in_r
     in_w.sync = true
 
     out_r, out_w = IO.pipe
-    opts[STDOUT] = out_w
+    opts[:out] = out_w
 
     popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
   end
@@ -149,11 +171,11 @@
     end
 
     in_r, in_w = IO.pipe
-    opts[STDIN] = in_r
+    opts[:in] = in_r
     in_w.sync = true
 
     out_r, out_w = IO.pipe
-    opts[[STDOUT, STDERR]] = out_w
+    opts[[:out, :err]] = out_w
 
     popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
   end
@@ -189,6 +211,14 @@
   #
   # Example:
   #
+  #   # dot is a command of graphviz.
+  #   graph = <<'End'
+  #     digraph g {
+  #       a -> b
+  #     }
+  #   End
+  #   layouted_graph, dot_log = Open3.poutput3("dot -v", :stdin_data=>graph)
+  #
   #   o, e, s = Open3.poutput3("echo a; sort >&2", :stdin_data=>"foo\nbar\nbaz\n")
   #   p o #=> "a\n"
   #   p e #=> "bar\nbaz\nfoo\n"
@@ -221,6 +251,10 @@
   #
   # If opts[:stdin_data] is specified, it is sent to the command's standard input.
   #
+  #   # factor is a command for integer factorization
+  #   o, s = Open3.poutput2("factor", :stdin_data=>"42")    
+  #   p o #=> "42: 2 3 7\n"
+  #
   def poutput2(*cmd, &block)
     if Hash === cmd.last
       opts = cmd.pop.dup
@@ -286,6 +320,12 @@
   #
   # Example:
   #
+  #   Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i,o,ts|
+  #     i.puts "All persons more than a mile high to leave the court."
+  #     i.close
+  #     p o.gets #=> "42\n"
+  #   }
+  #
   #   Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs|
   #     stdin.puts "foo"
   #     stdin.puts "bar"
@@ -301,11 +341,11 @@
     end
 
     in_r, in_w = IO.pipe
-    opts[STDIN] = in_r
+    opts[:in] = in_r
     in_w.sync = true
 
     out_r, out_w = IO.pipe
-    opts[STDOUT] = out_w
+    opts[:out] = out_w
 
     pipeline_run(cmds, opts, [in_r, out_w], [in_w, out_r], &block)
   end
@@ -329,6 +369,14 @@
   #     IO.copy_stream(r, STDOUT)
   #   }
   #
+  #   Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz",
+  #                    [{"LANG"=>"C"}, "grep", "GET /favicon.ico"],
+  #                    "logresolve") {|r, ts|
+  #     r.each_line {|line|
+  #       ...
+  #     }
+  #   }
+  #
   #   Open3.pipeline_r("yes", "head -10") {|r, ts|
   #     p r.read      #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"
   #     p ts[0].value #=> #<Process::Status: pid 24910 SIGPIPE (signal 13)>
@@ -343,7 +391,7 @@
     end
 
     out_r, out_w = IO.pipe
-    opts[STDOUT] = out_w
+    opts[:out] = out_w
 
     pipeline_run(cmds, opts, [out_w], [out_r], &block)
   end
@@ -362,11 +410,8 @@
   #
   # Example:
   #
-  #   Open3.pipeline_w("cat -n", "bzip2 -c", STDOUT=>"/tmp/z.bz2") {|w, ts|
+  #   Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|w, ts|
   #     w.puts "hello" 
-  #     w.close
-  #     p ts[0].value
-  #     p ts[1].value
   #   }
   #
   def pipeline_w(*cmds, &block)
@@ -377,21 +422,74 @@
     end
 
     in_r, in_w = IO.pipe
-    opts[STDIN] = in_r
+    opts[:in] = in_r
     in_w.sync = true
 
     pipeline_run(cmds, opts, [in_r], [in_w], &block)
   end
   module_function :pipeline_w
 
+  # Open3.pipeline_start starts list of commands as a pipeline.
+  # No pipe made for stdin of the first command and
+  # stdout of the last command.
+  #
+  #   Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads|
+  #     ...
+  #   }
+  #
+  #   wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts])
+  #   ...
+  #
+  def pipeline_start(*cmds, &block)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    pipeline_run(cmds, opts, [], [], &block)
+  end
+  module_function :pipeline_start
+
+  # Open3.pipeline starts list of commands as a pipeline.
+  # It waits the finish of the commands.
+  # No pipe made for stdin of the first command and
+  # stdout of the last command.
+  #
+  #   status_list = Open3.pipeline(cmd1, cmd2, ... [, opts])
+  #
+  # Example:
+  #
+  #   fname = "/usr/share/man/man1/ruby.1.gz"
+  #   p Open3.pipeline(["zcat", fname], "nroff -man", "less")   
+  #   #=> [#<Process::Status: pid 11817 exit 0>,
+  #   #    #<Process::Status: pid 11820 exit 0>,
+  #   #    #<Process::Status: pid 11828 exit 0>]
+  #
+  #   # count lines
+  #   Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count")
+  #
+  def pipeline(*cmds)
+    if Hash === cmds.last
+      opts = cmds.pop.dup
+    else
+      opts = {}
+    end
+
+    pipeline_run(cmds, opts, [], []) {|ts|
+      ts.map {|t| t.value }
+    }
+  end
+  module_function :pipeline
+
   def pipeline_run(cmds, pipeline_opts, child_io, parent_io, &block) # :nodoc:
     if cmds.empty?
       raise ArgumentError, "no commands"
     end
 
     opts_base = pipeline_opts.dup
-    opts_base.delete STDIN
-    opts_base.delete STDOUT
+    opts_base.delete :in
+    opts_base.delete :out
 
     wait_thrs = []
     r = nil
@@ -403,21 +501,21 @@
         cmd_opts.update cmd.pop if Hash === cmd.last
       end
       if i == 0
-        if !cmd_opts.include?(STDIN)
-          if pipeline_opts.include?(STDIN)
-            cmd_opts[STDIN] = pipeline_opts[STDIN]
+        if !cmd_opts.include?(:in)
+          if pipeline_opts.include?(:in)
+            cmd_opts[:in] = pipeline_opts[:in]
           end
         end
       else
-        cmd_opts[STDIN] = r
+        cmd_opts[:in] = r
       end
       if i != cmds.length - 1
         r2, w2 = IO.pipe
-        cmd_opts[STDOUT] = w2
+        cmd_opts[:out] = w2
       else
-        if !cmd_opts.include?(STDOUT)
-          if pipeline_opts.include?(STDOUT)
-            cmd_opts[STDOUT] = pipeline_opts[STDOUT]
+        if !cmd_opts.include?(:out)
+          if pipeline_opts.include?(:out)
+            cmd_opts[:out] = pipeline_opts[:out]
           end
         end
       end
Index: test/test_open3.rb
===================================================================
--- test/test_open3.rb	(revision 20543)
+++ test/test_open3.rb	(revision 20544)
@@ -196,4 +196,39 @@
     }
   end
 
+  def test_pipeline_start
+    command = [RUBY, '-e', 's=STDIN.read; print s[1..-1]; exit s[0] == ?t']
+    str = 'ttftff'
+    Open3.pipeline_start([RUBY, '-e', 'print ARGV[0]', str],
+                         *([command]*str.length)) {|ts|
+      assert_kind_of(Array, ts)
+      assert_equal(str.length+1, ts.length)
+      ts.each {|t| assert_kind_of(Thread, t) }
+      ts.each_with_index {|t, i|
+        if i == 0
+          assert(t.value.success?)
+        else
+          assert_equal(str[i-1] == ?t, t.value.success?)
+        end
+      }
+    }
+  end
+
+  def test_pipeline
+    command = [RUBY, '-e', 's=STDIN.read; print s[1..-1]; exit s[0] == ?t']
+    str = 'ttftff'
+    ss = Open3.pipeline([RUBY, '-e', 'print ARGV[0]', str],
+                        *([command]*str.length))
+    assert_kind_of(Array, ss)
+    assert_equal(str.length+1, ss.length)
+    ss.each {|s| assert_kind_of(Process::Status, s) }
+    ss.each_with_index {|s, i|
+      if i == 0
+        assert(s.success?)
+      else
+        assert_equal(str[i-1] == ?t, s.success?)
+      end
+    }
+  end
+
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]