File: errors.rb

package info (click to toggle)
ruby-process-executer 4.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 408 kB
  • sloc: ruby: 873; makefile: 4
file content (168 lines) | stat: -rw-r--r-- 5,572 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# frozen_string_literal: true

module ProcessExecuter
  # rubocop:disable Layout/LineLength

  # Base class for all {ProcessExecuter} errors
  #
  # It is recommended to rescue {ProcessExecuter::Error} to catch any runtime error
  # raised by this gem unless you need more specific error handling.
  #
  # Custom errors are arranged in the following class hierarchy:
  #
  # ```text
  # ::StandardError
  #   └─> Error
  #       ├─> ArgumentError
  #       ├─> CommandError
  #       │   ├─> FailedError
  #       │   └─> SignaledError
  #       │       └─> TimeoutError
  #       ├─> ProcessIOError
  #       └─> SpawnError
  # ```
  #
  # | Error Class | Description |
  # | --- | --- |
  # | `Error` | This catch-all error serves as the base class for other custom errors. |
  # | `ArgumentError` | Raised when an invalid argument is passed to a method. |
  # | `CommandError` | A subclass of this error is raised when there is a problem executing a command. |
  # | `FailedError` | Raised when the command exits with a non-zero exit status. |
  # | `SignaledError` | Raised when the command is terminated as a result of receiving a signal. This could happen if the process is forcibly terminated or if there is a serious system error. |
  # | `TimeoutError` | This is a specific type of `SignaledError` that is raised when the command times out and is killed via the SIGKILL signal. |
  # | `ProcessIOError` | Raised when an error was encountered reading or writing to the command's subprocess. |
  # | `SpawnError` | Raised when the process could not execute. Check the `#cause` for the original exception from `Process.spawn`.  |
  #
  # @example Rescuing any error
  #   begin
  #     ProcessExecuter.run('git', 'status')
  #   rescue ProcessExecuter::Error => e
  #     puts "An error occurred: #{e.message}"
  #   end
  #
  # @example Rescuing a timeout error
  #   begin
  #     timeout_after = 0.1 # seconds
  #     ProcessExecuter.run('sleep', '1', timeout_after:)
  #   rescue ProcessExecuter::TimeoutError => e # Catch the more specific error first!
  #     puts "Command took too long and timed out: #{e}"
  #   rescue ProcessExecuter::Error => e
  #     puts "Some other error occurred: #{e}"
  #   end
  #
  # @api public
  #
  class Error < ::StandardError; end

  # rubocop:enable Layout/LineLength

  # Raised when an invalid argument is passed to a method
  #
  # @example Raising ProcessExecuter::ArgumentError due to invalid option value
  #   begin
  #     ProcessExecuter.run('echo Hello', timeout_after: 'not_a_number')
  #   rescue ProcessExecuter::ArgumentError => e
  #     e.message #=> 'timeout_after must be nil or a non-negative real number but was "not_a_number"'
  #   end
  #
  # @api public
  #
  class ArgumentError < ProcessExecuter::Error; end

  # Raised when a command fails or exits because of an uncaught signal
  #
  # The command executed and its result are available from this object.
  #
  # This gem will raise a more specific error for each type of failure:
  #
  # * {FailedError}: when the command exits with a non-zero status
  # * {SignaledError}: when the command exits because of an uncaught signal
  # * {TimeoutError}: when the command times out
  #
  # @api public
  #
  class CommandError < ProcessExecuter::Error
    # Create a CommandError object
    #
    # @example
    #   `exit 1` # set $? appropriately for this example
    #   result_data = {
    #     command: ['exit 1'],
    #     options: ProcessExecuter::Options::RunOptions.new,
    #     timed_out: false,
    #     elapsed_time: 0.01
    #   }
    #   result = ProcessExecuter::Result.new($?, **result_data)
    #   error = ProcessExecuter::CommandError.new(result)
    #   error.to_s #=> '["exit 1"], status: pid 29686 exit 1'
    #
    # @param result [ProcessExecuter::Result] The result of the command including the
    #   command and exit status
    #
    def initialize(result)
      @result = result
      super(error_message)
    end

    # The human readable representation of this error
    #
    # @example
    #   error.error_message #=> '["git", "status"], status: pid 89784 exit 1'
    #
    # @return [String]
    #
    def error_message
      "#{result.command}, status: #{result}"
    end

    # @attribute [r] result
    #
    # The result of the command including the command, its status and its output
    #
    # @example
    #   error.result #=> #<ProcessExecuter::Result:0x00007f9b1b8b3d20>
    #
    # @return [ProcessExecuter::Result]
    #
    attr_reader :result
  end

  # Raised when the command returns a non-zero exit status
  #
  # @api public
  #
  class FailedError < ProcessExecuter::CommandError; end

  # Raised when the command exits because of an uncaught signal
  #
  # @api public
  #
  class SignaledError < ProcessExecuter::CommandError; end

  # Raised when the command takes longer than the configured timeout_after
  #
  # @example
  #   begin
  #     ProcessExecuter.spawn_with_timeout('sleep 1', timeout_after: 0.1)
  #   rescue ProcessExecuter::TimeoutError => e
  #     puts "Command timed out: #{e.result.command}"
  #   end
  #
  # @api public
  #
  class TimeoutError < ProcessExecuter::SignaledError; end

  # Raised if an exception occurred while processing subprocess output
  #
  # @api public
  #
  class ProcessIOError < ProcessExecuter::Error; end

  # Raised when spawn could not execute the process
  #
  # See the `cause` for the exception that Process.spawn raised.
  #
  # @api public
  #
  class SpawnError < ProcessExecuter::Error; end
end