subprocess 1.5.3 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4d97562256aef790c8c0a24420d8b6509375cc023809aaa833310d2e3c46442
4
- data.tar.gz: 9b91371b9e3e9a2af35431f69c4d3a795f02697063675378676bdb2f8cd7a262
3
+ metadata.gz: c82ea2c42d9357af9202aba5f361f28b50a60bba6d3350e3387f8bf71f7748e6
4
+ data.tar.gz: d12996089cab0fd638c31af1d2f73b1de63486eb482867887571c62e6fa0ec8d
5
5
  SHA512:
6
- metadata.gz: 7c757567b28d5e36cffd5ea13b705012ab790b445d757a1744a76d3eef375bfa6bc48259e0f0e744a351ee8455a79264a74dd9b6bcd6275c7fdd864b5b2ec82f
7
- data.tar.gz: fd3dd1fdbda8bcf00a2a96a7855610d2c9ff7fb2a6ec1d8f24751df80723f050444dbccd8bd93d3090210e4c7c6be033a008d46e7af550a0181fff0146a0329d
6
+ metadata.gz: 609beb788615d91132bf09e5febfc71eb8ae78d3534b1549f3a50389c340602c71119302e9718beb59d5344639a6de2577a01255876866e2661ccb674c626f17
7
+ data.tar.gz: 24e299e7a5337bbd5ea995fe72171e872d430081a207544fda7e5ab406d75fae4e98c8ec542ede5acced032f3765efd1f97dfbe839bfccb2c92d31b04c90f6d7
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Subprocess [![Build Status](https://travis-ci.org/stripe/subprocess.svg?branch=master)](https://travis-ci.org/stripe/subprocess) [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/stripe/subprocess/Subprocess)
1
+ # Subprocess ![Ruby](https://github.com/stripe/subprocess/workflows/Ruby/badge.svg) [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/stripe/subprocess/Subprocess)
2
2
 
3
3
  ![Jacques Cousteau Submarine](http://i.imgur.com/lmej24F.jpg)
4
4
 
@@ -65,6 +65,31 @@ differences, but if we have missed something, please file an issue.
65
65
  [python]: http://docs.python.org/library/subprocess.html
66
66
  [rubydoc]: http://rubydoc.info/github/stripe/subprocess/Subprocess
67
67
 
68
+ Maintenance
69
+ -----------
70
+
71
+ Steps to release a new version:
72
+
73
+ ```bash
74
+ # Work directly on master
75
+ git checkout master
76
+
77
+ # -- edit version in lib/subprocess/version.rb --
78
+
79
+ # Update RBI files
80
+ bundle exec rake sord
81
+
82
+ # Subsequent commands reference the version
83
+ VERSION=1.5.5
84
+ git commit -am "Bump version to $VERSION"
85
+ git tag "v$VERSION"
86
+ git push origin master --tags
87
+ bundle exec rake publish
88
+ ```
89
+
90
+ If you get errors, ask someone to add you to `bindings/rubygems-api-key` in
91
+ Vault or ask someone who already has permissions. See <http://go/password-vault>
92
+
68
93
  Acknowledgements
69
94
  ----------------
70
95
 
@@ -1,3 +1,3 @@
1
1
  module Subprocess
2
- VERSION = '1.5.3'
2
+ VERSION = '1.5.6'
3
3
  end
data/lib/subprocess.rb CHANGED
@@ -16,7 +16,13 @@ module Subprocess
16
16
 
17
17
  # An alias for `Process.new`. Mostly here to better emulate the Python API.
18
18
  #
19
+ # @param [Array<String>] cmd See {Process#initialize}
20
+ # @param [Hash] opts See {Process#initialize}
21
+ # @yield [process] See {Process#initialize}
22
+ # @yieldparam process [Process] See {Process#initialize}
19
23
  # @return [Process] A process with the given arguments
24
+ #
25
+ # @see Process#initialize
20
26
  def self.popen(cmd, opts={}, &blk)
21
27
  Process.new(cmd, opts, &blk)
22
28
  end
@@ -28,6 +34,11 @@ module Subprocess
28
34
  # fills up, as neither file descriptor will be read from. To avoid this, use
29
35
  # {Process#communicate} from a passed block.
30
36
  #
37
+ # @param [Array<String>] cmd See {Process#initialize}
38
+ # @param [Hash] opts See {Process#initialize}
39
+ # @yield [process] See {Process#initialize}
40
+ # @yieldparam process [Process] See {Process#initialize}
41
+ #
31
42
  # @return [::Process::Status] The exit status of the process
32
43
  #
33
44
  # @see Process#initialize
@@ -58,6 +69,11 @@ module Subprocess
58
69
  # fills up, as neither file descriptor will be read from. To avoid this, use
59
70
  # {Process#communicate} from a passed block.
60
71
  #
72
+ # @param [Array<String>] cmd See {Process#initialize}
73
+ # @param [Hash] opts See {Process#initialize}
74
+ # @yield [process] See {Process#initialize}
75
+ # @yieldparam process [Process] See {Process#initialize}
76
+ #
61
77
  # @raise [NonZeroExit] if the process returned a non-zero exit status (i.e.,
62
78
  # was terminated with an error or was killed by a signal)
63
79
  # @return [::Process::Status] The exit status of the process
@@ -70,11 +86,16 @@ module Subprocess
70
86
  end
71
87
 
72
88
  # Like {Subprocess::check_call}, but return the contents of `stdout`, much
73
- # like `Kernel#system`.
89
+ # like {::Kernel#system}.
74
90
  #
75
91
  # @example Get the system load
76
92
  # system_load = Subprocess.check_output(['uptime']).split(' ').last(3)
77
93
  #
94
+ # @param [Array<String>] cmd See {Process#initialize}
95
+ # @param [Hash] opts See {Process#initialize}
96
+ # @yield [process] See {Process#initialize}
97
+ # @yieldparam process [Process] See {Process#initialize}
98
+ #
78
99
  # @raise [NonZeroExit] if the process returned a non-zero exit status (i.e.,
79
100
  # was terminated with an error or was killed by a signal)
80
101
  # @return [String] The contents of `stdout`
@@ -130,16 +151,17 @@ module Subprocess
130
151
 
131
152
  # Error class representing a process's abnormal exit.
132
153
  class NonZeroExit < StandardError
133
- # @!attribute [r] command
134
- # @note This is intended only for use in user-facing error messages. In
135
- # particular, no shell quoting of any sort is performed when
136
- # constructing this string, meaning that blindly running it in a shell
137
- # might have different semantics than the original command.
138
- # @return [String] The command and arguments for the process that exited
139
- # abnormally.
140
- # @!attribute [r] status
141
- # @return [::Process::Status] The Ruby status object returned by `waitpid`
142
- attr_reader :command, :status
154
+ # @note This is intended only for use in user-facing error messages. In
155
+ # particular, no shell quoting of any sort is performed when
156
+ # constructing this string, meaning that blindly running it in a shell
157
+ # might have different semantics than the original command.
158
+ #
159
+ # @return [String] The command and arguments for the process that exited
160
+ # abnormally.
161
+ attr_reader :command
162
+
163
+ # @return [::Process::Status] The Ruby status object returned by `waitpid`
164
+ attr_reader :status
143
165
 
144
166
  # Return an instance of {NonZeroExit}.
145
167
  #
@@ -163,12 +185,15 @@ module Subprocess
163
185
 
164
186
  # Error class representing a timeout during a call to `communicate`
165
187
  class CommunicateTimeout < StandardError
166
- # @!attribute [r] stdout
167
- # @return [String] Content read from stdout before the timeout
168
- # @!attribute [r] stderr
169
- # @return [String] Content read from stderr before the timeout
170
- attr_reader :stdout, :stderr
188
+ # @return [String] Content read from stdout before the timeout
189
+ attr_reader :stdout
190
+
191
+ # @return [String] Content read from stderr before the timeout
192
+ attr_reader :stderr
171
193
 
194
+ # @param [Array<String>] cmd
195
+ # @param [String] stdout
196
+ # @param [String] stderr
172
197
  def initialize(cmd, stdout, stderr)
173
198
  @stdout = stdout
174
199
  @stderr = stderr
@@ -181,22 +206,24 @@ module Subprocess
181
206
  # functions on {Subprocess} (especially {Subprocess::check_call} and
182
207
  # {Subprocess::check_output}).
183
208
  class Process
184
- # @!attribute [r] stdin
185
- # @return [IO] The `IO` that is connected to this process's `stdin`.
186
- # @!attribute [r] stdout
187
- # @return [IO] The `IO` that is connected to this process's `stdout`.
188
- # @!attribute [r] stderr
189
- # @return [IO] The `IO` that is connected to this process's `stderr`.
190
- attr_reader :stdin, :stdout, :stderr
191
-
192
- # @!attribute [r] command
193
- # @return [Array<String>] The command this process was invoked with.
194
- # @!attribute [r] pid
195
- # @return [Fixnum] The process ID of the spawned process.
196
- # @!attribute [r] status
197
- # @return [::Process::Status] The exit status code of the process. Only
198
- # set after the process has exited.
199
- attr_reader :command, :pid, :status
209
+ # @return [IO] The `IO` that is connected to this process's `stdin`.
210
+ attr_reader :stdin
211
+
212
+ # @return [IO] The `IO` that is connected to this process's `stdout`.
213
+ attr_reader :stdout
214
+
215
+ # @return [IO] The `IO` that is connected to this process's `stderr`.
216
+ attr_reader :stderr
217
+
218
+ # @return [Array<String>] The command this process was invoked with.
219
+ attr_reader :command
220
+
221
+ # @return [Integer] The process ID of the spawned process.
222
+ attr_reader :pid
223
+
224
+ # @return [::Process::Status, nil] The exit status code of the process.
225
+ # Only set after the process has exited.
226
+ attr_reader :status
200
227
 
201
228
  # Create a new process.
202
229
  #
@@ -204,15 +231,15 @@ module Subprocess
204
231
  # style of an `argv` array). Unlike Python's subprocess module, `cmd`
205
232
  # cannot be a String.
206
233
  #
207
- # @option opts [IO, Fixnum, String, Subprocess::PIPE, nil] :stdin The `IO`,
234
+ # @option opts [IO, Integer, String, Subprocess::PIPE, nil] :stdin The `IO`,
208
235
  # file descriptor number, or file name to use for the process's standard
209
236
  # input. If the magic value {Subprocess::PIPE} is passed, a new pipe will
210
237
  # be opened.
211
- # @option opts [IO, Fixnum, String, Subprocess::PIPE, nil] :stdout The `IO`,
238
+ # @option opts [IO, Integer, String, Subprocess::PIPE, nil] :stdout The `IO`,
212
239
  # file descriptor number, or file name to use for the process's standard
213
240
  # output. If the magic value {Subprocess::PIPE} is passed, a pipe will be
214
241
  # opened and attached to the process.
215
- # @option opts [IO, Fixnum, String, Subprocess::PIPE, Subprocess::STDOUT,
242
+ # @option opts [IO, Integer, String, Subprocess::PIPE, Subprocess::STDOUT,
216
243
  # nil] :stderr The `IO`, file descriptor number, or file name to use for
217
244
  # the process's standard error. If the special value {Subprocess::PIPE} is
218
245
  # passed, a pipe will be opened and attached to the process. If the
@@ -223,12 +250,12 @@ module Subprocess
223
250
  # child process.
224
251
  # @option opts [Hash<String, String>] :env The environment to use in the
225
252
  # child process.
226
- # @option opts [Array<Fixnum>] :retain_fds An array of file descriptor
253
+ # @option opts [Array<Integer>] :retain_fds An array of file descriptor
227
254
  # numbers that should not be closed before executing the child process.
228
255
  # Note that, unlike Python (which has :close_fds defaulting to false), all
229
256
  # file descriptors not specified here will be closed.
230
257
  # @option opts [Hash] :exec_opts A hash that will be merged into the options
231
- # hash of the call to {Kernel#exec}.
258
+ # hash of the call to {::Kernel#exec}.
232
259
  #
233
260
  # @option opts [Proc] :preexec_fn A function that will be called in the
234
261
  # child process immediately before executing `cmd`.
@@ -403,7 +430,10 @@ module Subprocess
403
430
 
404
431
  stdout, stderr = "", ""
405
432
 
406
- input = input.dup unless input.nil?
433
+ # NB: Always force encoding to binary so we handle unicode or binary input
434
+ # correctly across multiple write_nonblock calls, since we manually slice
435
+ # the input depending on how many bytes were written
436
+ input = input.dup.force_encoding('BINARY') unless input.nil?
407
437
 
408
438
  @stdin.close if (input.nil? || input.empty?) && !@stdin.nil?
409
439
 
@@ -469,7 +499,7 @@ module Subprocess
469
499
  @stdin.close
470
500
  wait_w.delete(@stdin)
471
501
  end
472
- input[0...written] = ''
502
+ input = input[written..input.length]
473
503
  if input.empty?
474
504
  @stdin.close
475
505
  wait_w.delete(@stdin)
@@ -494,15 +524,23 @@ module Subprocess
494
524
 
495
525
  # Does exactly what it says on the box.
496
526
  #
497
- # @param [String, Symbol, Fixnum] signal The signal to send to the child
527
+ # @param [String, Symbol, Integer] signal The signal to send to the child
498
528
  # process. Accepts all the same arguments as Ruby's built-in
499
529
  # {::Process::kill}, for instance a string like "INT" or "SIGINT", or a
500
530
  # signal number like 2.
531
+ #
532
+ # @return [Integer] See {::Process.kill}
533
+ #
534
+ # @see ::Process.kill
501
535
  def send_signal(signal)
502
536
  ::Process.kill(signal, pid)
503
537
  end
504
538
 
505
539
  # Sends `SIGTERM` to the process.
540
+ #
541
+ # @return [Integer] See {send_signal}
542
+ #
543
+ # @see send_signal
506
544
  def terminate
507
545
  send_signal("TERM")
508
546
  end
@@ -512,6 +550,10 @@ module Subprocess
512
550
  # descriptor should appear to the child and to this process, respectively.
513
551
  # "mine" is only non-nil in the case of a pipe (in fact, we just return a
514
552
  # list of length one, since ruby will unpack nils from missing list items).
553
+ #
554
+ # @param [IO, Integer, String, nil] fd
555
+ # @param [String] mode
556
+ # @return [Array<IO>]
515
557
  def parse_fd(fd, mode)
516
558
  fds = case fd
517
559
  when PIPE
@@ -533,6 +575,9 @@ module Subprocess
533
575
 
534
576
  # The pair to parse_fd, returns whether or not the file descriptor was
535
577
  # opened by us (and therefore should be closed by us).
578
+ #
579
+ # @param [IO, Integer, String, nil] fd
580
+ # @return [Boolean]
536
581
  def our_fd?(fd)
537
582
  case fd
538
583
  when PIPE, String
@@ -543,6 +588,12 @@ module Subprocess
543
588
  end
544
589
 
545
590
  # Call IO.select timing out at Time `timeout_at`. If `timeout_at` is nil, never times out.
591
+ #
592
+ # @param [Array<IO>, nil] read_array
593
+ # @param [Array<IO>, nil] write_array
594
+ # @param [Array<IO>, nil] err_array
595
+ # @param [Integer, Float, nil] timeout_at
596
+ # @return [Array<Array<IO>>, nil]
546
597
  def select_until(read_array, write_array, err_array, timeout_at)
547
598
  if !timeout_at
548
599
  return IO.select(read_array, write_array, err_array)
@@ -561,6 +612,7 @@ module Subprocess
561
612
  @sigchld_global_read = nil
562
613
  @sigchld_pipe_pid = nil
563
614
 
615
+ # @return [void]
564
616
  def self.handle_sigchld
565
617
  # We'd like to just notify everything in `@sigchld_fds`, but
566
618
  # ruby signal handlers are not executed atomically with respect
@@ -583,6 +635,7 @@ module Subprocess
583
635
  # and we want to let the process itself do that. In practice, we're not
584
636
  # likely to have that many in-flight subprocesses, so this is probably not a
585
637
  # big deal.
638
+ # @return [void]
586
639
  def self.wakeup_sigchld
587
640
  @sigchld_mutex.synchronize do
588
641
  @sigchld_fds.values.each do |fd|
@@ -598,6 +651,9 @@ module Subprocess
598
651
  end
599
652
  end
600
653
 
654
+ # @param [Integer] pid
655
+ # @param [IO] fd
656
+ # @return [void]
601
657
  def self.register_pid(pid, fd)
602
658
  @sigchld_mutex.synchronize do
603
659
  @sigchld_fds[pid] = fd
@@ -615,6 +671,8 @@ module Subprocess
615
671
  end
616
672
  end
617
673
 
674
+ # @param [Integer] pid
675
+ # @return [void]
618
676
  def self.unregister_pid(pid)
619
677
  @sigchld_mutex.synchronize do
620
678
  if @sigchld_fds.length == 1
@@ -624,6 +682,8 @@ module Subprocess
624
682
  end
625
683
  end
626
684
 
685
+ # @param [Integer] pid
686
+ # @return [void]
627
687
  def self.catching_sigchld(pid)
628
688
  IO.pipe do |self_read, self_write|
629
689
  begin
@@ -0,0 +1,312 @@
1
+ # typed: strong
2
+
3
+ # THIS FILE IS AUTOGENERATED. DO NOT EDIT.
4
+ # To regenerate from YARD comments:
5
+ #
6
+ # bundle exec rake sord
7
+ #
8
+ # A Ruby clone of Python's subprocess module.
9
+ #
10
+ # @see http://docs.python.org/2/library/subprocess.html
11
+ module ::Subprocess
12
+ PIPE = T.let(-1, T.untyped)
13
+ STDOUT = T.let(-2, T.untyped)
14
+ VERSION = T.let('1.5.5', T.untyped)
15
+
16
+ # An alias for `Process.new`. Mostly here to better emulate the Python API.
17
+ #
18
+ # _@param_ `cmd` — See {Process#initialize}
19
+ #
20
+ # _@param_ `opts` — See {Process#initialize}
21
+ #
22
+ # _@return_ — A process with the given arguments
23
+ #
24
+ # _@see_ `Process#initialize`
25
+ sig { params(cmd: T::Array[String], opts: T::Hash[T.untyped, T.untyped], blk: T.nilable(T.proc.params(process: Process).void)).returns(Process) }
26
+ def self.popen(cmd, opts = {}, &blk); end
27
+
28
+ # Call and wait for the return of a given process.
29
+ #
30
+ # _@param_ `cmd` — See {Process#initialize}
31
+ #
32
+ # _@param_ `opts` — See {Process#initialize}
33
+ #
34
+ # _@return_ — The exit status of the process
35
+ #
36
+ # _@note_ — If you call this function with `:stdout => PIPE` or `:stderr => PIPE`,
37
+ # this function will block indefinitely as soon as the OS's pipe buffer
38
+ # fills up, as neither file descriptor will be read from. To avoid this, use
39
+ # {Process#communicate} from a passed block.
40
+ #
41
+ # _@see_ `Process#initialize`
42
+ sig { params(cmd: T::Array[String], opts: T::Hash[T.untyped, T.untyped], blk: T.nilable(T.proc.params(process: Process).void)).returns(::Process::Status) }
43
+ def self.call(cmd, opts = {}, &blk); end
44
+
45
+ # Like {Subprocess::call}, except raise a {NonZeroExit} if the process did not
46
+ # terminate successfully.
47
+ #
48
+ # _@param_ `cmd` — See {Process#initialize}
49
+ #
50
+ # _@param_ `opts` — See {Process#initialize}
51
+ #
52
+ # _@return_ — The exit status of the process
53
+ #
54
+ # Grep a file for a string
55
+ # ```ruby
56
+ # Subprocess.check_call(%W{grep -q llama ~/favorite_animals})
57
+ # ```
58
+ #
59
+ # Communicate with a child process
60
+ # ```ruby
61
+ # Subprocess.check_call(%W{sendmail -t}, :stdin => Subprocess::PIPE) do |p|
62
+ # p.communicate <<-EMAIL
63
+ # From: alpaca@example.com
64
+ # To: llama@example.com
65
+ # Subject: I am so fluffy.
66
+ #
67
+ # SO FLUFFY!
68
+ # http://upload.wikimedia.org/wikipedia/commons/3/3e/Unshorn_alpaca_grazing.jpg
69
+ # EMAIL
70
+ # end
71
+ # ```
72
+ #
73
+ # _@note_ — If you call this function with `:stdout => PIPE` or `:stderr => PIPE`,
74
+ # this function will block indefinitely as soon as the OS's pipe buffer
75
+ # fills up, as neither file descriptor will be read from. To avoid this, use
76
+ # {Process#communicate} from a passed block.
77
+ #
78
+ # _@see_ `Process#initialize`
79
+ sig { params(cmd: T::Array[String], opts: T::Hash[T.untyped, T.untyped], blk: T.nilable(T.proc.params(process: Process).void)).returns(::Process::Status) }
80
+ def self.check_call(cmd, opts = {}, &blk); end
81
+
82
+ # Like {Subprocess::check_call}, but return the contents of `stdout`, much
83
+ # like {::Kernel#system}.
84
+ #
85
+ # _@param_ `cmd` — See {Process#initialize}
86
+ #
87
+ # _@param_ `opts` — See {Process#initialize}
88
+ #
89
+ # _@return_ — The contents of `stdout`
90
+ #
91
+ # Get the system load
92
+ # ```ruby
93
+ # system_load = Subprocess.check_output(['uptime']).split(' ').last(3)
94
+ # ```
95
+ #
96
+ # _@see_ `Process#initialize`
97
+ sig { params(cmd: T::Array[String], opts: T::Hash[T.untyped, T.untyped], blk: T.nilable(T.proc.params(process: Process).void)).returns(String) }
98
+ def self.check_output(cmd, opts = {}, &blk); end
99
+
100
+ # Print a human readable interpretation of a process exit status.
101
+ #
102
+ # _@param_ `status` — The status returned by `waitpid2`.
103
+ #
104
+ # _@param_ `convert_high_exit` — Whether to convert exit statuses greater than 128 into the usual convention for exiting after trapping a signal. (e.g. many programs will exit with status 130 after receiving a SIGINT / signal 2.)
105
+ #
106
+ # _@return_ — Text interpretation
107
+ sig { params(status: ::Process::Status, convert_high_exit: T::Boolean).returns(String) }
108
+ def self.status_to_s(status, convert_high_exit = true); end
109
+
110
+ # Error class representing a process's abnormal exit.
111
+ class NonZeroExit < StandardError
112
+ # Return an instance of {NonZeroExit}.
113
+ #
114
+ # _@param_ `cmd` — The command that returned a non-zero status.
115
+ #
116
+ # _@param_ `status` — The status returned by `waitpid`.
117
+ sig { params(cmd: T::Array[String], status: ::Process::Status).void }
118
+ def initialize(cmd, status); end
119
+
120
+ # _@return_ — The command and arguments for the process that exited
121
+ # abnormally.
122
+ #
123
+ # _@note_ — This is intended only for use in user-facing error messages. In
124
+ # particular, no shell quoting of any sort is performed when
125
+ # constructing this string, meaning that blindly running it in a shell
126
+ # might have different semantics than the original command.
127
+ sig { returns(String) }
128
+ attr_reader :command
129
+
130
+ # _@return_ — The Ruby status object returned by `waitpid`
131
+ sig { returns(::Process::Status) }
132
+ attr_reader :status
133
+ end
134
+
135
+ # Error class representing a timeout during a call to `communicate`
136
+ class CommunicateTimeout < StandardError
137
+ # _@param_ `cmd`
138
+ #
139
+ # _@param_ `stdout`
140
+ #
141
+ # _@param_ `stderr`
142
+ sig { params(cmd: T::Array[String], stdout: String, stderr: String).void }
143
+ def initialize(cmd, stdout, stderr); end
144
+
145
+ # _@return_ — Content read from stdout before the timeout
146
+ sig { returns(String) }
147
+ attr_reader :stdout
148
+
149
+ # _@return_ — Content read from stderr before the timeout
150
+ sig { returns(String) }
151
+ attr_reader :stderr
152
+ end
153
+
154
+ # A child process. The preferred way of spawning a subprocess is through the
155
+ # functions on {Subprocess} (especially {Subprocess::check_call} and
156
+ # {Subprocess::check_output}).
157
+ class Process
158
+ # Create a new process.
159
+ #
160
+ # _@param_ `cmd` — The command to run and its arguments (in the style of an `argv` array). Unlike Python's subprocess module, `cmd` cannot be a String.
161
+ sig { params(cmd: T::Array[String], opts: T::Hash[T.untyped, T.untyped], blk: T.nilable(T.proc.params(process: Process).void)).void }
162
+ def initialize(cmd, opts = {}, &blk); end
163
+
164
+ # Poll the child, setting (and returning) its status. If the child has not
165
+ # terminated, return nil and exit immediately
166
+ #
167
+ # _@return_ — The exit status of the process
168
+ sig { returns(T.nilable(::Process::Status)) }
169
+ def poll; end
170
+
171
+ # Wait for the child to return, setting and returning the status of the
172
+ # child.
173
+ #
174
+ # _@return_ — The exit status of the process
175
+ sig { returns(::Process::Status) }
176
+ def wait; end
177
+
178
+ # Do nonblocking reads from `fd`, appending all data read into `buf`.
179
+ #
180
+ # _@param_ `fd` — The file to read from.
181
+ #
182
+ # _@param_ `buf` — A buffer to append the read data to.
183
+ #
184
+ # _@return_ — Whether `fd` was closed due to an exceptional
185
+ # condition (`EOFError` or `EPIPE`).
186
+ sig { params(fd: IO, buf: T.nilable(String)).returns(T::Boolean) }
187
+ def drain_fd(fd, buf = nil); end
188
+
189
+ # Write the (optional) input to the process's `stdin` and read the contents of
190
+ # `stdout` and `stderr`. If a block is provided, stdout and stderr are yielded as they
191
+ # are read. Otherwise they are buffered in memory and returned when the process
192
+ # exits. Do this all using `IO::select`, so we don't deadlock due to full pipe
193
+ # buffers.
194
+ #
195
+ # This is only really useful if you set some of `:stdin`, `:stdout`, and
196
+ # `:stderr` to {Subprocess::PIPE}.
197
+ #
198
+ # _@param_ `input` — A string to feed to the child's standard input.
199
+ #
200
+ # _@param_ `timeout_s` — Raise {Subprocess::CommunicateTimeout} if communicate does not finish after timeout_s seconds.
201
+ #
202
+ # _@return_ — An array of two elements: the data read from the
203
+ # child's standard output and standard error, respectively.
204
+ # Returns nil if a block is provided.
205
+ sig { params(input: T.nilable(String), timeout_s: T.nilable(Numeric)).returns([String, String]) }
206
+ def communicate(input = nil, timeout_s = nil); end
207
+
208
+ # Does exactly what it says on the box.
209
+ #
210
+ # _@param_ `signal` — The signal to send to the child process. Accepts all the same arguments as Ruby's built-in {::Process::kill}, for instance a string like "INT" or "SIGINT", or a signal number like 2.
211
+ #
212
+ # _@return_ — See {::Process.kill}
213
+ #
214
+ # _@see_ `::Process.kill`
215
+ sig { params(signal: T.any(String, Symbol, Integer)).returns(Integer) }
216
+ def send_signal(signal); end
217
+
218
+ # Sends `SIGTERM` to the process.
219
+ #
220
+ # _@return_ — See {send_signal}
221
+ #
222
+ # _@see_ `send_signal`
223
+ sig { returns(Integer) }
224
+ def terminate; end
225
+
226
+ # Return a pair of values (child, mine), which are how the given file
227
+ # descriptor should appear to the child and to this process, respectively.
228
+ # "mine" is only non-nil in the case of a pipe (in fact, we just return a
229
+ # list of length one, since ruby will unpack nils from missing list items).
230
+ #
231
+ # _@param_ `fd`
232
+ #
233
+ # _@param_ `mode`
234
+ sig { params(fd: T.nilable(T.any(IO, Integer, String)), mode: String).returns(T::Array[IO]) }
235
+ def parse_fd(fd, mode); end
236
+
237
+ # The pair to parse_fd, returns whether or not the file descriptor was
238
+ # opened by us (and therefore should be closed by us).
239
+ #
240
+ # _@param_ `fd`
241
+ sig { params(fd: T.nilable(T.any(IO, Integer, String))).returns(T::Boolean) }
242
+ def our_fd?(fd); end
243
+
244
+ # Call IO.select timing out at Time `timeout_at`. If `timeout_at` is nil, never times out.
245
+ #
246
+ # _@param_ `read_array`
247
+ #
248
+ # _@param_ `write_array`
249
+ #
250
+ # _@param_ `err_array`
251
+ #
252
+ # _@param_ `timeout_at`
253
+ sig do
254
+ params(
255
+ read_array: T.nilable(T::Array[IO]),
256
+ write_array: T.nilable(T::Array[IO]),
257
+ err_array: T.nilable(T::Array[IO]),
258
+ timeout_at: T.nilable(T.any(Integer, Float))
259
+ ).returns(T.nilable(T::Array[T::Array[IO]]))
260
+ end
261
+ def select_until(read_array, write_array, err_array, timeout_at); end
262
+
263
+ sig { void }
264
+ def self.handle_sigchld; end
265
+
266
+ # Wake up everyone. We can't tell who we should wake up without `wait`ing,
267
+ # and we want to let the process itself do that. In practice, we're not
268
+ # likely to have that many in-flight subprocesses, so this is probably not a
269
+ # big deal.
270
+ sig { void }
271
+ def self.wakeup_sigchld; end
272
+
273
+ # _@param_ `pid`
274
+ #
275
+ # _@param_ `fd`
276
+ sig { params(pid: Integer, fd: IO).void }
277
+ def self.register_pid(pid, fd); end
278
+
279
+ # _@param_ `pid`
280
+ sig { params(pid: Integer).void }
281
+ def self.unregister_pid(pid); end
282
+
283
+ # _@param_ `pid`
284
+ sig { params(pid: Integer).void }
285
+ def self.catching_sigchld(pid); end
286
+
287
+ # _@return_ — The `IO` that is connected to this process's `stdin`.
288
+ sig { returns(IO) }
289
+ attr_reader :stdin
290
+
291
+ # _@return_ — The `IO` that is connected to this process's `stdout`.
292
+ sig { returns(IO) }
293
+ attr_reader :stdout
294
+
295
+ # _@return_ — The `IO` that is connected to this process's `stderr`.
296
+ sig { returns(IO) }
297
+ attr_reader :stderr
298
+
299
+ # _@return_ — The command this process was invoked with.
300
+ sig { returns(T::Array[String]) }
301
+ attr_reader :command
302
+
303
+ # _@return_ — The process ID of the spawned process.
304
+ sig { returns(Integer) }
305
+ attr_reader :pid
306
+
307
+ # _@return_ — The exit status code of the process.
308
+ # Only set after the process has exited.
309
+ sig { returns(T.nilable(::Process::Status)) }
310
+ attr_reader :status
311
+ end
312
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subprocess
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Jackson
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2020-04-06 00:00:00.000000000 Z
15
+ date: 2022-06-08 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: minitest
@@ -56,6 +56,20 @@ dependencies:
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
58
  version: '0'
59
+ - !ruby/object:Gem::Dependency
60
+ name: sord
61
+ requirement: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
59
73
  description: Control and communicate with spawned processes
60
74
  email:
61
75
  - carl@stripe.com
@@ -70,6 +84,7 @@ files:
70
84
  - README.md
71
85
  - lib/subprocess.rb
72
86
  - lib/subprocess/version.rb
87
+ - rbi/subprocess.rbi
73
88
  homepage: https://github.com/stripe/subprocess
74
89
  licenses:
75
90
  - MIT