slop 4.9.3 → 4.10.0

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: 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