slop 4.9.2 → 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: db594ae38cd4d8b8d078d3b3854e5dce764f4763107caacc02b0b270c33098d8
4
- data.tar.gz: 6e1348ca3f3d642bff87411d33c78b2f3d1b654c11c079a228f327f82648cd5f
3
+ metadata.gz: 2d4b4855a341f5e05c71ec19242556039ea85f4d339560dec38c24beb8831691
4
+ data.tar.gz: 95fcb3512ee937216387467758a05992d72bbfad627fd79b939277a204c941ad
5
5
  SHA512:
6
- metadata.gz: b578d6d172adf2b9c88d482fe27798d97a821b83ef7ff4f8b6e8ed37d63cd7f7963b9634b9f734e80d744c0fc077f47bc2a08e00feed02af90452c6415383494
7
- data.tar.gz: 8fc6007694ba5df48585ac6561c1ec68cf50141d92cb6f080d50b6de700a0244aefd3d3d647f7ccee197c57cfcd3ad4721b2c88039ab6f9667cb47d4dc705620
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,17 @@
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
+
9
+ v4.9.3 (2022-09-30)
10
+ -------------------
11
+
12
+ Bug fixes:
13
+ * Fix explicitly false boolean options and allow for additional false arguments [#276](https://github.com/leejarvis/slop/pull/276) (Eugene Otto)
14
+
4
15
  v4.9.2 (2022-03-26)
5
16
  -------------------
6
17
 
data/README.md CHANGED
@@ -22,17 +22,19 @@ opts = Slop.parse do |o|
22
22
  o.bool '-v', '--verbose', 'enable verbose mode'
23
23
  o.bool '-q', '--quiet', 'suppress output (quiet mode)'
24
24
  o.bool '-c', '--check-ssl-certificate', 'check SSL certificate for host'
25
+ o.bool '-k', '--use-keychain', 'store passphrase in OS keychain'
25
26
  o.on '--version', 'print the version' do
26
27
  puts Slop::VERSION
27
28
  exit
28
29
  end
29
30
  end
30
31
 
31
- ARGV #=> -v --login alice --host 192.168.0.1 -m post --check-ssl-certificate
32
+ ARGV #=> -v --login alice --host 192.168.0.1 -m post --check-ssl-certificate --use-keychain false
32
33
 
33
34
  opts[:host] #=> 192.168.0.1
34
35
  opts[:login] #=> alice
35
36
  opts[:method] #=> :post
37
+ opts[:use_keychain] #=> false
36
38
  opts.verbose? #=> true
37
39
  opts.quiet? #=> false
38
40
  opts.check_ssl_certificate? #=> true
@@ -53,7 +55,7 @@ Built in Option types are as follows:
53
55
 
54
56
  ```ruby
55
57
  o.string #=> Slop::StringOption, expects an argument
56
- o.bool #=> Slop::BoolOption, no argument, aliased to BooleanOption
58
+ o.bool #=> Slop::BoolOption, argument optional, aliased to BooleanOption
57
59
  o.integer #=> Slop::IntegerOption, expects an argument, aliased to IntOption
58
60
  o.float #=> Slop::FloatOption, expects an argument
59
61
  o.array #=> Slop::ArrayOption, expects an argument
@@ -202,6 +204,8 @@ Slop will raise errors for the following:
202
204
  * An option used without an argument when it expects one: `Slop::MissingArgument`
203
205
  * An option used that Slop doesn't know about: `Slop::UnknownOption`
204
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`
205
209
 
206
210
  These errors inherit from `Slop::Error`, so you can rescue them all.
207
211
  Alternatively you can suppress these errors with the `suppress_errors` config
@@ -220,6 +224,33 @@ opts = Slop.parse do
220
224
  end
221
225
  ```
222
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
+
223
254
  Printing help
224
255
  -------------
225
256
 
@@ -277,4 +308,4 @@ end
277
308
  Commands
278
309
  --------
279
310
 
280
- 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
@@ -21,6 +21,15 @@ module Slop
21
21
  class BoolOption < Option
22
22
  attr_accessor :explicit_value
23
23
 
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
32
+
24
33
  def call(value)
25
34
  self.explicit_value = value
26
35
  !force_false?
@@ -35,7 +44,7 @@ module Slop
35
44
  end
36
45
 
37
46
  def force_false?
38
- explicit_value == false
47
+ FALSE_VALUES.include?(explicit_value)
39
48
  end
40
49
 
41
50
  def default_value
@@ -50,8 +59,14 @@ module Slop
50
59
 
51
60
  # Cast the option argument to an Integer.
52
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
+
53
68
  def call(value)
54
- value =~ /\A[+-]?\d+\z/ && value.to_i
69
+ value.to_i
55
70
  end
56
71
  end
57
72
  IntOption = IntegerOption
@@ -60,8 +75,12 @@ module Slop
60
75
  class FloatOption < Option
61
76
  FLOAT_STRING_REGEXP = /\A[+-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?\z/.freeze
62
77
 
78
+ def valid?(value)
79
+ value =~ FLOAT_STRING_REGEXP
80
+ end
81
+
63
82
  def call(value)
64
- value =~ FLOAT_STRING_REGEXP && value.to_f
83
+ value.to_f
65
84
  end
66
85
  end
67
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.2'
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,12 +31,14 @@ 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", validate_type: true
37
38
  @bloc = @options.bool("--bloc"){|val| (@bloc_val ||= []) << val}
38
39
  @result = @options.parse %w(--verbose --no-inversed
39
- --bloc --no-bloc)
40
+ --bloc --no-bloc
41
+ --explicit=false)
40
42
  end
41
43
 
42
44
  it "returns true if used" do
@@ -54,13 +56,23 @@ describe Slop::BoolOption do
54
56
  it "will invert the value passed to &block via --no- prefix" do
55
57
  assert_equal [true, false], @bloc_val
56
58
  end
59
+
60
+ it "returns false when explicitly false" do
61
+ assert_equal false, @result[:explicit]
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
57
69
  end
58
70
 
59
71
  describe Slop::IntegerOption do
60
72
  before do
61
73
  @options = Slop::Options.new
62
74
  @age = @options.integer "--age"
63
- @minus = @options.integer "--minus"
75
+ @minus = @options.integer "--minus", validate_type: true
64
76
  @plus = @options.integer "--plus"
65
77
  @result = @options.parse %w(--age 20 --minus -10 --plus +30)
66
78
  end
@@ -75,6 +87,12 @@ describe Slop::IntegerOption do
75
87
  @result.parser.parse %w(--age hello)
76
88
  assert_nil @result[:age]
77
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
78
96
  end
79
97
 
80
98
  describe Slop::FloatOption do
@@ -82,7 +100,7 @@ describe Slop::FloatOption do
82
100
  @options = Slop::Options.new
83
101
  @apr = @options.float "--apr"
84
102
  @apr_value = 2.9
85
- @minus = @options.float "--minus"
103
+ @minus = @options.float "--minus", validate_type: true
86
104
  @plus = @options.float "--plus"
87
105
  @scientific_notation = @options.float "--scientific-notation"
88
106
  @scientific_notation_value = 4e21
@@ -119,6 +137,12 @@ describe Slop::FloatOption do
119
137
  @result.parser.parse %w(--apr hello)
120
138
  assert_nil @result[:apr]
121
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
122
146
  end
123
147
 
124
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.2
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-03-26 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
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
88
  requirements: []
89
- rubygems_version: 3.2.32
89
+ rubygems_version: 3.3.7
90
90
  signing_key:
91
91
  specification_version: 4
92
92
  summary: Simple Lightweight Option Parsing