Skip to content

Commit aa04661

Browse files
authored
Merge pull request #2714 from ksss/open3-capture3
Add signature for `Open3.capture3`
2 parents 2b0a633 + f396796 commit aa04661

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

stdlib/open3/0/open3.rbs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,104 @@ module Open3
246246
def self?.capture2e: (*String, ?stdin_data: String, ?binmode: boolish) -> [String, Process::Status]
247247
| (env, *String, ?stdin_data: String, ?binmode: boolish) -> [String, Process::Status]
248248

249+
# <!--
250+
# rdoc-file=lib/open3.rb
251+
# - Open3.capture3([env, ] command_line, options = {}) -> [stdout_s, stderr_s, status]
252+
# - Open3.capture3([env, ] exe_path, *args, options = {}) -> [stdout_s, stderr_s, status]
253+
# -->
254+
# Basically a wrapper for Open3.popen3 that:
255+
#
256+
# * Creates a child process, by calling Open3.popen3 with the given arguments
257+
# (except for certain entries in hash `options`; see below).
258+
# * Returns as strings `stdout_s` and `stderr_s` the standard output and
259+
# standard error of the child process.
260+
# * Returns as `status` a `Process::Status` object that represents the exit
261+
# status of the child process.
262+
#
263+
# Returns the array `[stdout_s, stderr_s, status]`:
264+
#
265+
# stdout_s, stderr_s, status = Open3.capture3('echo "Foo"')
266+
# # => ["Foo\n", "", #<Process::Status: pid 2281954 exit 0>]
267+
#
268+
# Like Process.spawn, this method has potential security vulnerabilities if
269+
# called with untrusted input; see [Command
270+
# Injection](rdoc-ref:command_injection.rdoc@Command+Injection).
271+
#
272+
# Unlike Process.spawn, this method waits for the child process to exit before
273+
# returning, so the caller need not do so.
274+
#
275+
# If the first argument is a hash, it becomes leading argument `env` in the call
276+
# to Open3.popen3; see [Execution
277+
# Environment](rdoc-ref:Process@Execution+Environment).
278+
#
279+
# If the last argument is a hash, it becomes trailing argument `options` in the
280+
# call to Open3.popen3; see [Execution
281+
# Options](rdoc-ref:Process@Execution+Options).
282+
#
283+
# The hash `options` is given; two options have local effect in method
284+
# Open3.capture3:
285+
#
286+
# * If entry `options[:stdin_data]` exists, the entry is removed and its
287+
# string value is sent to the command's standard input:
288+
#
289+
# Open3.capture3('tee', stdin_data: 'Foo')
290+
# # => ["Foo", "", #<Process::Status: pid 2319575 exit 0>]
291+
#
292+
# * If entry `options[:binmode]` exists, the entry is removed and the internal
293+
# streams are set to binary mode.
294+
#
295+
# The single required argument is one of the following:
296+
#
297+
# * `command_line` if it is a string, and if it begins with a shell reserved
298+
# word or special built-in, or if it contains one or more metacharacters.
299+
# * `exe_path` otherwise.
300+
#
301+
# **Argument `command_line`**
302+
#
303+
# String argument `command_line` is a command line to be passed to a shell; it
304+
# must begin with a shell reserved word, begin with a special built-in, or
305+
# contain meta characters:
306+
#
307+
# Open3.capture3('if true; then echo "Foo"; fi') # Shell reserved word.
308+
# # => ["Foo\n", "", #<Process::Status: pid 2282025 exit 0>]
309+
# Open3.capture3('echo') # Built-in.
310+
# # => ["\n", "", #<Process::Status: pid 2282092 exit 0>]
311+
# Open3.capture3('date > date.tmp') # Contains meta character.
312+
# # => ["", "", #<Process::Status: pid 2282110 exit 0>]
313+
#
314+
# The command line may also contain arguments and options for the command:
315+
#
316+
# Open3.capture3('echo "Foo"')
317+
# # => ["Foo\n", "", #<Process::Status: pid 2282092 exit 0>]
318+
#
319+
# **Argument `exe_path`**
320+
#
321+
# Argument `exe_path` is one of the following:
322+
#
323+
# * The string path to an executable to be called.
324+
# * A 2-element array containing the path to an executable and the string to
325+
# be used as the name of the executing process.
326+
#
327+
# Example:
328+
#
329+
# Open3.capture3('/usr/bin/date')
330+
# # => ["Thu Sep 28 05:03:51 PM CDT 2023\n", "", #<Process::Status: pid 2282300 exit 0>]
331+
#
332+
# Ruby invokes the executable directly, with no shell and no shell expansion:
333+
#
334+
# Open3.capture3('doesnt_exist') # Raises Errno::ENOENT
335+
#
336+
# If one or more `args` is given, each is an argument or option to be passed to
337+
# the executable:
338+
#
339+
# Open3.capture3('echo', 'C #')
340+
# # => ["C #\n", "", #<Process::Status: pid 2282368 exit 0>]
341+
# Open3.capture3('echo', 'hello', 'world')
342+
# # => ["hello world\n", "", #<Process::Status: pid 2282372 exit 0>]
343+
#
344+
def self?.capture3: (*String, ?stdin_data: String, ?binmode: boolish) -> [String, String, Process::Status]
345+
| (env, *String, ?stdin_data: String, ?binmode: boolish) -> [String, String, Process::Status]
346+
249347
# <!--
250348
# rdoc-file=lib/open3.rb
251349
# - Open3.popen3([env, ] command_line, options = {}) -> [stdin, stdout, stderr, wait_thread]

test/stdlib/Open3_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ def test_capture2e
2828
Open3, :capture2e, { 'FOO' => 'BAR' }, "echo $FOO"
2929
end
3030

31+
def test_capture3
32+
assert_send_type "(*::String) -> [ ::String, ::String, ::Process::Status ]",
33+
Open3, :capture3, 'echo "Foo"'
34+
assert_send_type "(*::String, binmode: boolish) -> [ ::String, ::String, ::Process::Status ]",
35+
Open3, :capture3, 'echo "Foo"', binmode: true
36+
assert_send_type "(*::String, stdin_data: ::String) -> [ ::String, ::String, ::Process::Status ]",
37+
Open3, :capture3, "#{RUBY_EXECUTABLE} -e 'puts STDIN.read'", stdin_data: 'Foo'
38+
assert_send_type "(::Hash[::String, ::String], *::String) -> [ ::String, ::String, ::Process::Status ]",
39+
Open3, :capture3, { 'FOO' => 'BAR' }, "echo $FOO"
40+
end
41+
3142
def test_popen3
3243
assert_send_type "(::String) -> [ ::IO, ::IO, ::IO, ::Process::Waiter ]",
3344
Open3, :popen3, 'echo "Foo"'

0 commit comments

Comments
 (0)