slop 4.9.3 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e59ff0d4bd9fa111d71e057b9e3ae9aa1aebef93937fcf7f1e1d57fb789c010
4
- data.tar.gz: 1628f1e9cfa67ca737b494b65d135d4b28ee7f16fb9b9bfeb746d54a2d83b1b4
3
+ metadata.gz: 2d4b4855a341f5e05c71ec19242556039ea85f4d339560dec38c24beb8831691
4
+ data.tar.gz: 95fcb3512ee937216387467758a05992d72bbfad627fd79b939277a204c941ad
5
5
  SHA512:
6
- metadata.gz: 1f1aea5c8faeb6d7d6a995f3853b97f9c8c80ed57fcaf692c3113fb5b7b4886323677e4adf5e6595975748beaca585d700949f3739dc82f81913563bc7b9a318
7
- data.tar.gz: c75a58a1341a177152ae5d8827d3f980d6a395854123c2ab5612837835c723123c38d84239e299a50012f5b3ce017566244efa41bcfb97bfbc53a077867e9bea
6
+ metadata.gz: c0ecc669117cf0c6336e3dfb1cf65c5019a0d638205a2497511121e102f7af7f48f175ded4c03d382257710da679970e4e405b84bee44a0613781d90b5bd4b63
7
+ data.tar.gz: 867c2ef751092ce4fafe9010f1b6ddb9ec7ee9adcdd2d020353129e7189b3ea8224f33ac368b773cca1298c297b159054775fb71074691e8ce9e20f780a58388
@@ -22,10 +22,10 @@ jobs:
22
22
  strategy:
23
23
  fail-fast: false
24
24
  matrix:
25
- ruby: [ "2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", head, jruby, truffleruby ]
25
+ ruby: [ "2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "3.0", "3.1", "3.2", head, jruby, truffleruby ]
26
26
  name: Ruby ${{ matrix.ruby }}
27
27
  steps:
28
- - uses: actions/checkout@v2
28
+ - uses: actions/checkout@v3
29
29
  - name: Set up Ruby
30
30
  uses: ruby/setup-ruby@v1
31
31
  with:
data/CHANGELOG.md CHANGED
@@ -1,6 +1,11 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v4.10.0 (2023-02-15)
5
+
6
+ Features:
7
+ * Add support for optional type validation [#278](https://github.com/leejarvis/slop/pull/278) (Victor Gama)
8
+
4
9
  v4.9.3 (2022-09-30)
5
10
  -------------------
6
11
 
data/README.md CHANGED
@@ -204,6 +204,8 @@ Slop will raise errors for the following:
204
204
  * An option used without an argument when it expects one: `Slop::MissingArgument`
205
205
  * An option used that Slop doesn't know about: `Slop::UnknownOption`
206
206
  * An option marked as `required` when not provided: `Slop::MissingRequiredOption`
207
+ * An option marked as `validate_types`, with an argument that does not match its
208
+ type (i.e. `bla` for `integer`): `Slop::InvalidOptionValue`
207
209
 
208
210
  These errors inherit from `Slop::Error`, so you can rescue them all.
209
211
  Alternatively you can suppress these errors with the `suppress_errors` config
@@ -222,6 +224,33 @@ opts = Slop.parse do
222
224
  end
223
225
  ```
224
226
 
227
+ Validating Types
228
+ ----------------
229
+
230
+ By default, Slop does not validate whether an argument is a valid value for a
231
+ given option; instead, if the option has a default value, it will be used over
232
+ the invalid argument provided.
233
+ In order to have types (such as `integer` and `float`) validate and indicate
234
+ that the provided value is invalid, an extra option can be either provided to
235
+ the argument itself, or its option set:
236
+
237
+ ```ruby
238
+ opts = Slop::Options.new
239
+ opts.int "-p", "--port", "a port", default: 80, validate_types: true
240
+
241
+ parser = Slop::Parser.new(opts)
242
+ result = parser.parse(["--port", "bla"])
243
+ # invalid value for -p, --port (Slop::InvalidOptionValue)
244
+
245
+ # Or to the option set...
246
+ opts = Slop::Options.new(validate_types: true)
247
+ opts.int "-p", "--port", "a port", default: 80
248
+
249
+ parser = Slop::Parser.new(opts)
250
+ result = parser.parse(["--port", "bla"])
251
+ # invalid value for -p, --port (Slop::InvalidOptionValue)
252
+ ```
253
+
225
254
  Printing help
226
255
  -------------
227
256
 
@@ -279,4 +308,4 @@ end
279
308
  Commands
280
309
  --------
281
310
 
282
- Slop not longer has built in support for git-style subcommands.
311
+ Slop no longer has built in support for git-style subcommands.
data/lib/slop/error.rb CHANGED
@@ -38,4 +38,16 @@ module Slop
38
38
  # Suppress with the `suppress_errors` config option.
39
39
  class MissingRequiredOption < Error
40
40
  end
41
+
42
+ # Raised when a given option is provided by the user and does not
43
+ # match the expected format for that type. This is only raised if
44
+ # validate_types is set to true.
45
+ class InvalidOptionValue < Error
46
+ attr_reader :flag
47
+
48
+ def initialize(msg, flag)
49
+ super(msg)
50
+ @flag = flag
51
+ end
52
+ end
41
53
  end
data/lib/slop/option.rb CHANGED
@@ -56,7 +56,11 @@ module Slop
56
56
  raise Slop::MissingArgument.new("missing argument for #{flag}", flags)
57
57
  end
58
58
  else
59
- @value = call(value)
59
+ if validate_type? && !valid?(value) && !suppress_errors?
60
+ raise Slop::InvalidOptionValue.new("invalid value for #{flag}", flags)
61
+ end
62
+
63
+ @value = valid?(value) && call(value)
60
64
  end
61
65
 
62
66
  block.call(@value) if block.respond_to?(:call)
@@ -107,6 +111,13 @@ module Slop
107
111
  config[:required]
108
112
  end
109
113
 
114
+ # Returns true if an exception should be raised when this option value can't
115
+ # be parsed into the desired type or does not conform to the expected type's
116
+ # format
117
+ def validate_type?
118
+ config[:validate_type] || config[:validate_types]
119
+ end
120
+
110
121
  # Returns all flags joined by a comma. Used by the help string.
111
122
  def flag
112
123
  flags.join(", ")
@@ -119,6 +130,13 @@ module Slop
119
130
  key.to_sym
120
131
  end
121
132
 
133
+ # Override this if you want to provide a custom validator for a type. This
134
+ # method must return whether the provided value is valid for the current
135
+ # argument's type
136
+ def valid?(value)
137
+ true
138
+ end
139
+
122
140
  # Returns true if this option should be displayed with dashes transformed into underscores.
123
141
  def underscore_flags?
124
142
  config[:underscore_flags]
data/lib/slop/options.rb CHANGED
@@ -7,6 +7,7 @@ module Slop
7
7
  type: "null",
8
8
  banner: true,
9
9
  underscore_flags: true,
10
+ validate_types: false,
10
11
  }
11
12
 
12
13
  # The Array of Option instances we've created.
@@ -24,6 +25,9 @@ module Slop
24
25
  # The String banner prefixed to the help string.
25
26
  attr_accessor :banner
26
27
 
28
+ # Whether we should validate types of values provided by the user
29
+ attr_accessor :validate_types
30
+
27
31
  def initialize(**config, &block)
28
32
  @options = []
29
33
  @separators = []
data/lib/slop/types.rb CHANGED
@@ -22,6 +22,13 @@ module Slop
22
22
  attr_accessor :explicit_value
23
23
 
24
24
  FALSE_VALUES = [false, 'false', 'no', 'off', '0'].freeze
25
+ TRUE_VALUES = [true, 'true', 'yes', 'on', '1'].freeze
26
+ VALID_VALUES = (FALSE_VALUES + TRUE_VALUES).freeze
27
+
28
+ def valid?(value)
29
+ return true if value.is_a?(String) && value.start_with?("--")
30
+ value.nil? || VALID_VALUES.include?(value)
31
+ end
25
32
 
26
33
  def call(value)
27
34
  self.explicit_value = value
@@ -52,8 +59,14 @@ module Slop
52
59
 
53
60
  # Cast the option argument to an Integer.
54
61
  class IntegerOption < Option
62
+ INT_STRING_REGEXP = /\A[+-]?\d+\z/.freeze
63
+
64
+ def valid?(value)
65
+ value =~ INT_STRING_REGEXP
66
+ end
67
+
55
68
  def call(value)
56
- value =~ /\A[+-]?\d+\z/ && value.to_i
69
+ value.to_i
57
70
  end
58
71
  end
59
72
  IntOption = IntegerOption
@@ -62,8 +75,12 @@ module Slop
62
75
  class FloatOption < Option
63
76
  FLOAT_STRING_REGEXP = /\A[+-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?\z/.freeze
64
77
 
78
+ def valid?(value)
79
+ value =~ FLOAT_STRING_REGEXP
80
+ end
81
+
65
82
  def call(value)
66
- value =~ FLOAT_STRING_REGEXP && value.to_f
83
+ value.to_f
67
84
  end
68
85
  end
69
86
 
data/lib/slop.rb CHANGED
@@ -6,7 +6,7 @@ require 'slop/types'
6
6
  require 'slop/error'
7
7
 
8
8
  module Slop
9
- VERSION = '4.9.3'
9
+ VERSION = '4.10.0'
10
10
 
11
11
  # Parse an array of options (defaults to ARGV). Accepts an
12
12
  # optional hash of configuration options and block.
data/test/error_test.rb CHANGED
@@ -63,3 +63,18 @@ describe Slop::MissingRequiredOption do
63
63
  opts.parse []
64
64
  end
65
65
  end
66
+
67
+ describe Slop::InvalidOptionValue do
68
+ it "raises when an option has an invalid value" do
69
+ opts = Slop::Options.new(validate_types: true)
70
+ opts.integer "-n", "--number", default: 10
71
+ assert_raises(Slop::InvalidOptionValue) { opts.parse %w(-n foo) }
72
+ end
73
+
74
+ it "does not raise when errors are suppressed" do
75
+ opts = Slop::Options.new(suppress_errors: true)
76
+ opts.integer "-n", "--number", default: 10, validate_type: true
77
+ r = opts.parse %w(-n foo)
78
+ assert_equal(10, r[:n])
79
+ end
80
+ end
data/test/types_test.rb CHANGED
@@ -31,10 +31,10 @@ end
31
31
  describe Slop::BoolOption do
32
32
  before do
33
33
  @options = Slop::Options.new
34
- @verbose = @options.bool "--verbose"
34
+ @verbose = @options.bool "--verbose", validate_type: true
35
35
  @quiet = @options.bool "--quiet"
36
36
  @inversed = @options.bool "--inversed", default: true
37
- @explicit = @options.bool "--explicit"
37
+ @explicit = @options.bool "--explicit", validate_type: true
38
38
  @bloc = @options.bool("--bloc"){|val| (@bloc_val ||= []) << val}
39
39
  @result = @options.parse %w(--verbose --no-inversed
40
40
  --bloc --no-bloc
@@ -60,13 +60,19 @@ describe Slop::BoolOption do
60
60
  it "returns false when explicitly false" do
61
61
  assert_equal false, @result[:explicit]
62
62
  end
63
+
64
+ it "raises with invalid types" do
65
+ assert_raises(Slop::InvalidOptionValue) do
66
+ @result.parser.parse %w(--verbose foo)
67
+ end
68
+ end
63
69
  end
64
70
 
65
71
  describe Slop::IntegerOption do
66
72
  before do
67
73
  @options = Slop::Options.new
68
74
  @age = @options.integer "--age"
69
- @minus = @options.integer "--minus"
75
+ @minus = @options.integer "--minus", validate_type: true
70
76
  @plus = @options.integer "--plus"
71
77
  @result = @options.parse %w(--age 20 --minus -10 --plus +30)
72
78
  end
@@ -81,6 +87,12 @@ describe Slop::IntegerOption do
81
87
  @result.parser.parse %w(--age hello)
82
88
  assert_nil @result[:age]
83
89
  end
90
+
91
+ it "raises with invalid types" do
92
+ assert_raises(Slop::InvalidOptionValue) do
93
+ @result.parser.parse %w(--minus foo)
94
+ end
95
+ end
84
96
  end
85
97
 
86
98
  describe Slop::FloatOption do
@@ -88,7 +100,7 @@ describe Slop::FloatOption do
88
100
  @options = Slop::Options.new
89
101
  @apr = @options.float "--apr"
90
102
  @apr_value = 2.9
91
- @minus = @options.float "--minus"
103
+ @minus = @options.float "--minus", validate_type: true
92
104
  @plus = @options.float "--plus"
93
105
  @scientific_notation = @options.float "--scientific-notation"
94
106
  @scientific_notation_value = 4e21
@@ -125,6 +137,12 @@ describe Slop::FloatOption do
125
137
  @result.parser.parse %w(--apr hello)
126
138
  assert_nil @result[:apr]
127
139
  end
140
+
141
+ it "raises with invalid types" do
142
+ assert_raises(Slop::InvalidOptionValue) do
143
+ @result.parser.parse %w(--minus foo)
144
+ end
145
+ end
128
146
  end
129
147
 
130
148
  describe Slop::ArrayOption do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slop
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.9.3
4
+ version: 4.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Jarvis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-30 00:00:00.000000000 Z
11
+ date: 2023-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake