command_mapper 0.1.0 → 0.1.1

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: 7d3986821a50009055f2fe58c4f69e7eb530b5463114f73f838997743c8227fe
4
- data.tar.gz: dc0ca8143917f12ef8cb72601f5a2ff44cccd6c76c0fdbc23fc75bafff571ff5
3
+ metadata.gz: 4db5d03aecac93251d259d3b776a33706bc328208a9fb58c4a96966d87128ed8
4
+ data.tar.gz: bc67f06449dc8b0b7c5061c55a315112dcf3fab2bf548314e4f20a6b2dbdd67f
5
5
  SHA512:
6
- metadata.gz: dfaccdfb0892218f9e3b8661d2c80227d492c292407989d3bb2b2ffabe45806898549d463a9bb0aa54fe05092753b0751e797460a94c19849552675b75309ec2
7
- data.tar.gz: 4bc76e0cd50aaaf790331ce2aab5acac98562c7ed63cd3979a90429cad836ee4e095ab765aa22b57c17eff9bc89fb92f9ed1b09f97d98fe4ab47cfa38dbcc99a
6
+ metadata.gz: 9e99f9216620e3847fc8e250d0c05d549f547396eef01a519d332cd3927cd86c71ed26e862fda84f26f28570e180f76eb1fb9117729a737bcf718de33f2d0886
7
+ data.tar.gz: a3766529ada1866b7736e905d3ba65511eea1b2e9679b9edad99e57089285159a307beb726ee7b1f2f2c02e6eb6d34d569d86babb3f79dc3be54527e834fbacd
data/ChangeLog.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### 0.1.1 / 2021-11-29
2
+
3
+ * Fixed a bug where {CommandMapper::Types::Num}, {CommandMapper::Types::Hex},
4
+ {CommandMapper::Types::Enum}, {CommandMapper::Types::InputPath},
5
+ {CommandMapper::Types::InputFile}, and {CommandMapper::Types::InputDir} were
6
+ not being required by default.
7
+ * Allow {CommandMapper::Types::Map} to accept values that have already been
8
+ mapped to a String.
9
+
1
10
  ### 0.1.0 / 2021-11-25
2
11
 
3
12
  * Initial release:
data/README.md CHANGED
@@ -18,21 +18,26 @@ allow safely and securely executing commands.
18
18
  * Supports defining commands as Ruby classes.
19
19
  * Supports mapping in options and additional arguments.
20
20
  * Supports common option types:
21
- * `Str`: string values
22
- * `Num`: numeric values
23
- * `Hex`: hexadecimal values
24
- * `Map`: maps `true`/`false` to `yes`/`no`, or `enabled`/`disabled`
25
- (aka `--opt=yes|no` or `--opt=enabled|disabled` values).
26
- * `Enum`: maps a finite set of Symbols to a finite set of Strings
27
- (aka `--opt={foo|bar|baz}` values).
28
- * `List`: comma-separated list (aka `--opt VALUE,...`).
29
- * `KeyValue`: maps a Hash or Array to key:value Strings
30
- (aka `--opt KEY:VALUE` or `--opt KEY=VALUE` values).
31
- * `KeyValueList`: a key-value list
21
+ * [Str][CommandMapper::Types::Str]: string values
22
+ * [Num][CommandMapper::Types::Num]: numeric values
23
+ * [Hex][CommandMapper::Types::Hex]: hexadecimal values
24
+ * [Map][CommandMapper::Types::Map]: maps `true`/`false` to `yes`/`no`, or
25
+ `enabled`/`disabled` (aka `--opt=yes|no` or
26
+ `--opt=enabled|disabled` values).
27
+ * [Enum][CommandMapper::Types::Enum]: maps a finite set of Symbols to a
28
+ finite set of Strings (aka `--opt={foo|bar|baz}` values).
29
+ * [List][CommandMapper::Types::List]: comma-separated list
30
+ (aka `--opt VALUE,...`).
31
+ * [KeyValue][CommandMapper::Types::KeyValue]: maps a Hash or Array to
32
+ key:value Strings (aka `--opt KEY:VALUE` or `--opt KEY=VALUE` values).
33
+ * [KeyValueList][CommandMapper::Types::KeyValueList]: a key-value list
32
34
  (aka `--opt KEY:VALUE,...` or `--opt KEY=VALUE;...` values).
33
- * `InputPath`: a path to a pre-existing file or directory
34
- * `InputFile`: a path to a pre-existing file
35
- * `InputDir`: a path to a pre-existing directory
35
+ * [InputPath][CommandMapper::Types::InputPath]: a path to a pre-existing
36
+ file or directory
37
+ * [InputFile][CommandMapper::Types::InputFile]: a path to a pre-existing
38
+ file
39
+ * [InputDir][CommandMapper::Types::InputDir]: a path to a pre-existing
40
+ directory
36
41
  * Supports mapping in sub-commands.
37
42
  * Allows running the command via `IO.popen` to read the command's output.
38
43
  * Allows running commands with additional environment variables.
@@ -40,6 +45,18 @@ allow safely and securely executing commands.
40
45
  * Allows running commands via `sudo`.
41
46
  * Prevents command injection and option injection.
42
47
 
48
+ [CommandMapper::Types::Str]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Str
49
+ [CommandMapper::Types::Num]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Num
50
+ [CommandMapper::Types::Hex]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Hex
51
+ [CommandMapper::Types::Map]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Map
52
+ [CommandMapper::Types::Enum]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Enum
53
+ [CommandMapper::Types::List]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/List
54
+ [CommandMapper::Types::KeyValue]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/KeyValue
55
+ [CommandMapper::Types::KeyValueList]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/KeyValueList
56
+ [CommandMapper::Types::InputPath]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/InputPath
57
+ [CommandMapper::Types::InputFile]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/InputFile
58
+ [CommandMapper::Types::InputDir]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/InputDir
59
+
43
60
  ## Examples
44
61
 
45
62
  ```ruby
@@ -18,6 +18,7 @@ module CommandMapper
18
18
  # Specifies whether the argument is required or can be omitted.
19
19
  #
20
20
  # @param [Types::Type, Hash, nil] type
21
+ # The type of the arg's value.
21
22
  #
22
23
  # @raise [ArgumentError]
23
24
  # The `type` keyword argument was given a `nil` value.
@@ -54,6 +55,7 @@ module CommandMapper
54
55
  # Validates whether a given value is compatible with the arg.
55
56
  #
56
57
  # @param [Object] value
58
+ # The given value to validate.
57
59
  #
58
60
  # @return [true, (false, String)]
59
61
  # Returns true if the value is valid, or `false` and a validation error
@@ -50,6 +50,7 @@ module CommandMapper
50
50
  # Validates whether a given value is compatible with the arg.
51
51
  #
52
52
  # @param [Array<Object>, Object] value
53
+ # The given value to validate.
53
54
  #
54
55
  # @return [true, (false, String)]
55
56
  # Returns true if the value is valid, or `false` and a validation error
@@ -113,6 +113,7 @@ module CommandMapper
113
113
  # Validates whether the given value is compatible with the option.
114
114
  #
115
115
  # @param [Array<Object>, Object] value
116
+ # The given value to validate.
116
117
  #
117
118
  # @return [true, (false, String)]
118
119
  # Returns true if the value is valid, or `false` and a validation error
@@ -175,6 +176,7 @@ module CommandMapper
175
176
  # Validates a value when the option can be repeated.
176
177
  #
177
178
  # @param [Array<Object>, Object] value
179
+ # The given value to validate.
178
180
  #
179
181
  # @return [true, (false, String)]
180
182
  # Returns true if the value is valid, or `false` and a validation error
@@ -208,6 +210,7 @@ module CommandMapper
208
210
  # Validates a value when the option does not accept a value.
209
211
  #
210
212
  # @param [Array<Object>, Object] value
213
+ # The given value to validate.
211
214
  #
212
215
  # @return [true, (false, String)]
213
216
  # Returns true if the value is valid, or `false` and a validation error
@@ -10,8 +10,10 @@ module CommandMapper
10
10
  # Formats a value using the options {#type}.
11
11
  #
12
12
  # @param [Object] value
13
+ # The given value to format.
13
14
  #
14
15
  # @return [String]
16
+ # The formatted value.
15
17
  #
16
18
  def format(value)
17
19
  @type.format(value)
@@ -23,8 +23,10 @@ module CommandMapper
23
23
  # Creates a new enum.
24
24
  #
25
25
  # @param [Array<Object>] values
26
+ # List of enum values.
26
27
  #
27
28
  # @return [Enum]
29
+ # The newly created enum object.
28
30
  #
29
31
  def self.[](*values)
30
32
  new(values)
@@ -33,8 +33,11 @@ module CommandMapper
33
33
  # Validates a value.
34
34
  #
35
35
  # @param [String, Integer, Object] value
36
+ # The given value to validate.
36
37
  #
37
38
  # @return [true, (false, String)]
39
+ # Returns true if the value is valid, or `false` and a validation error
40
+ # message if the value is not compatible.
38
41
  #
39
42
  def validate(value)
40
43
  case value
@@ -53,8 +56,10 @@ module CommandMapper
53
56
  # Formats the value.
54
57
  #
55
58
  # @param [#to_i] value
59
+ # The given numeric value.
56
60
  #
57
61
  # @return [String]
62
+ # The formatted numeric value.
58
63
  #
59
64
  def format(value)
60
65
  case value
@@ -11,8 +11,11 @@ module CommandMapper
11
11
  # Validates whether the directory exists.
12
12
  #
13
13
  # @param [Object] value
14
+ # The given value to validate.
14
15
  #
15
16
  # @return [true, (false, String)]
17
+ # Returns true if the value is valid, or `false` and a validation error
18
+ # message if the value is not compatible.
16
19
  #
17
20
  def validate(value)
18
21
  valid, message = super(value)
@@ -11,8 +11,11 @@ module CommandMapper
11
11
  # Validates the file exists.
12
12
  #
13
13
  # @param [Object] value
14
+ # The given value to validate.
14
15
  #
15
16
  # @return [true, (false, String)]
17
+ # Returns true if the value is valid, or `false` and a validation error
18
+ # message if the value is not compatible.
16
19
  #
17
20
  def validate(value)
18
21
  valid, message = super(value)
@@ -11,8 +11,11 @@ module CommandMapper
11
11
  # Validates whether the path exists or not.
12
12
  #
13
13
  # @param [Object] value
14
+ # The given value to validate.
14
15
  #
15
16
  # @return [true, (false, String)]
17
+ # Returns true if the value is valid, or `false` and a validation error
18
+ # message if the value is not compatible.
16
19
  #
17
20
  def validate(value)
18
21
  unless value.empty?
@@ -57,8 +57,11 @@ module CommandMapper
57
57
  # Valides the given value.
58
58
  #
59
59
  # @param [Object] value
60
+ # The given value to validate.
60
61
  #
61
62
  # @return [true, (false, String)]
63
+ # Returns true if the value is valid, or `false` and a validation error
64
+ # message if the value is not compatible.
62
65
  #
63
66
  def validate(value)
64
67
  case value
@@ -105,7 +108,7 @@ module CommandMapper
105
108
  # Formats a value into a key-value pair.
106
109
  #
107
110
  # @param [Hash, Array, #to_s] value
108
- # The given value.
111
+ # The given value to format.
109
112
  #
110
113
  # @return [String]
111
114
  # The formatted key-value pair.
@@ -31,7 +31,7 @@ module CommandMapper
31
31
  # Formats the value.
32
32
  #
33
33
  # @param [Hash, Array((key, value))] value
34
- # The list of key-value pairs.
34
+ # The list of key-value pairs to format.
35
35
  #
36
36
  # @return [String]
37
37
  # The formatted key-value list.
@@ -51,8 +51,11 @@ module CommandMapper
51
51
  # Validates the value.
52
52
  #
53
53
  # @param [Object] value
54
+ # The given value to validate.
54
55
  #
55
56
  # @return [true, (false, String)]
57
+ # Returns true if the value is valid, or `false` and a validation error
58
+ # message if the value is not compatible.
56
59
  #
57
60
  def validate(value)
58
61
  values = Array(value)
@@ -78,8 +81,10 @@ module CommandMapper
78
81
  # Formats the value into a list.
79
82
  #
80
83
  # @param [Object] value
84
+ # The given value to format.
81
85
  #
82
86
  # @return [String]
87
+ # The formatted list.
83
88
  #
84
89
  def format(value)
85
90
  Array(value).map(&@type.method(:format)).join(@separator)
@@ -39,24 +39,40 @@ module CommandMapper
39
39
  # Validates a value.
40
40
  #
41
41
  # @param [Object] value
42
+ # The given value to validate.
42
43
  #
43
44
  # @return [true, (false, String)]
45
+ # Returns true if the value is valid, or `false` and a validation error
46
+ # message if the value is not compatible.
44
47
  #
45
48
  def validate(value)
46
- unless @map.has_key?(value)
49
+ unless (@map.has_key?(value) || @map.has_value?(value))
47
50
  return [false, "unknown value (#{value.inspect})"]
48
51
  end
49
52
 
50
53
  return true
51
54
  end
52
55
 
56
+ #
57
+ # Maps a value.
53
58
  #
54
59
  # @param [Object] value
60
+ # The given value.
55
61
  #
56
62
  # @return [String]
63
+ # The mapped value.
64
+ #
65
+ # @raise [KeyError]
66
+ # The given value is not a key or value in the map.
57
67
  #
58
68
  def format(value)
59
- super(@map.fetch(value))
69
+ if @map.has_key?(value)
70
+ super(@map[value])
71
+ elsif @map.has_value?(value)
72
+ super(value)
73
+ else
74
+ raise(KeyError,"value (#{value.inspect}) is not a key or value in the map: #{@map.inspect}")
75
+ end
60
76
  end
61
77
 
62
78
  end
@@ -11,8 +11,11 @@ module CommandMapper
11
11
  # Validates a value.
12
12
  #
13
13
  # @param [String, Integer] value
14
+ # The given value to validate.
14
15
  #
15
16
  # @return [true, (false, String)]
17
+ # Returns true if the value is valid, or `false` and a validation error
18
+ # message if the value is not compatible.
16
19
  #
17
20
  def validate(value)
18
21
  case value
@@ -35,8 +38,10 @@ module CommandMapper
35
38
  # Formats a numeric value.
36
39
  #
37
40
  # @param [String, Integer, #to_i] value
41
+ # The given value to format.
38
42
  #
39
43
  # @return [String]
44
+ # The formatted numeric value.
40
45
  #
41
46
  def format(value)
42
47
  case value
@@ -56,8 +56,11 @@ module CommandMapper
56
56
  # The default `validate` method for all types.
57
57
  #
58
58
  # @param [Object]
59
+ # The given value to format.
59
60
  #
60
61
  # @return [true, (false, String)]
62
+ # Returns true if the value is valid, or `false` and a validation error
63
+ # message if the value is not compatible.
61
64
  #
62
65
  def validate(value)
63
66
  true
@@ -67,6 +70,7 @@ module CommandMapper
67
70
  # The default `format` method for all types.
68
71
  #
69
72
  # @param [#to_s] value
73
+ # The given value to format.
70
74
  #
71
75
  # @return [String]
72
76
  # The String version of the value.
@@ -83,10 +87,14 @@ module CommandMapper
83
87
  # Converts a value into a {Type} object.
84
88
  #
85
89
  # @param [Type, Hash, nil] value
90
+ # The type value or `Hash` of keyword arguments.
86
91
  #
87
- # @return [Type]
92
+ # @return [Type, Str]
93
+ # The type object or a new {Str} type object if a `Hash` of keyword
94
+ # arguments is given.
88
95
  #
89
96
  # @raise [ArgumentError]
97
+ # The given type value was not a {Type}, `Hash`, or `nil`,
90
98
  #
91
99
  def self.Type(value)
92
100
  case value
@@ -1,6 +1,12 @@
1
1
  require 'command_mapper/types/type'
2
2
  require 'command_mapper/types/str'
3
+ require 'command_mapper/types/num'
4
+ require 'command_mapper/types/hex'
3
5
  require 'command_mapper/types/map'
6
+ require 'command_mapper/types/enum'
4
7
  require 'command_mapper/types/list'
5
8
  require 'command_mapper/types/key_value'
6
9
  require 'command_mapper/types/key_value_list'
10
+ require 'command_mapper/types/input_path'
11
+ require 'command_mapper/types/input_file'
12
+ require 'command_mapper/types/input_dir'
@@ -1,4 +1,4 @@
1
1
  module CommandMapper
2
2
  # Version of command_mapper
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
data/spec/commnad_spec.rb CHANGED
@@ -11,6 +11,10 @@ describe CommandMapper::Command do
11
11
  end
12
12
  end
13
13
 
14
+ it "must include Types" do
15
+ expect(command_class).to include(CommandMapper::Types)
16
+ end
17
+
14
18
  describe ".command_name" do
15
19
  subject { command_class }
16
20
 
@@ -22,13 +22,22 @@ describe CommandMapper::Types::Map do
22
22
  end
23
23
 
24
24
  describe "#validate" do
25
- context "when given a value that's in the map" do
25
+ context "when given a value that's a key in the map" do
26
26
  let(:value) { 2 }
27
27
 
28
28
  it "must return true" do
29
29
  expect(subject.validate(value)).to be(true)
30
30
  end
31
31
  end
32
+
33
+ context "when given a value that's a value in the map" do
34
+ let(:value) { "two" }
35
+
36
+ it "must return true" do
37
+ expect(subject.validate(value)).to be(true)
38
+ end
39
+ end
40
+
32
41
  context "when given a value that is not in the map" do
33
42
  let(:value) { 42 }
34
43
 
@@ -41,7 +50,7 @@ describe CommandMapper::Types::Map do
41
50
  end
42
51
 
43
52
  describe "#format" do
44
- context "when given a value that's in the map" do
53
+ context "when given a value that's a key in the map" do
45
54
  let(:value) { 2 }
46
55
 
47
56
  it "must return the corresponding mapped value" do
@@ -49,13 +58,21 @@ describe CommandMapper::Types::Map do
49
58
  end
50
59
  end
51
60
 
61
+ context "when given a value that's a value in the map" do
62
+ let(:value) { "two" }
63
+
64
+ it "must return the value" do
65
+ expect(subject.format(value)).to eq(value)
66
+ end
67
+ end
68
+
52
69
  context "when given a value that is not in the map" do
53
70
  let(:value) { 42 }
54
71
 
55
72
  it "must return the String version of the value" do
56
73
  expect {
57
74
  subject.format(value)
58
- }.to raise_error(KeyError)
75
+ }.to raise_error(KeyError,"value (#{value.inspect}) is not a key or value in the map: #{map.inspect}")
59
76
  end
60
77
  end
61
78
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'command_mapper/types'
3
+
4
+ describe CommandMapper::Types do
5
+ it "must define a Str type" do
6
+ expect(subject.const_defined?('Str')).to be(true)
7
+ end
8
+
9
+ it "must define a Num type" do
10
+ expect(subject.const_defined?('Num')).to be(true)
11
+ end
12
+
13
+ it "must define a Hex type" do
14
+ expect(subject.const_defined?('Hex')).to be(true)
15
+ end
16
+
17
+ it "must define a Map type" do
18
+ expect(subject.const_defined?('Map')).to be(true)
19
+ end
20
+
21
+ it "must define a Enum type" do
22
+ expect(subject.const_defined?('Enum')).to be(true)
23
+ end
24
+
25
+ it "must define a List type" do
26
+ expect(subject.const_defined?('List')).to be(true)
27
+ end
28
+
29
+ it "must define a KeyValue type" do
30
+ expect(subject.const_defined?('KeyValue')).to be(true)
31
+ end
32
+
33
+ it "must define a KeyValueList type" do
34
+ expect(subject.const_defined?('KeyValueList')).to be(true)
35
+ end
36
+
37
+ it "must define a InputPath type" do
38
+ expect(subject.const_defined?('InputPath')).to be(true)
39
+ end
40
+
41
+ it "must define a InputFile type" do
42
+ expect(subject.const_defined?('InputFile')).to be(true)
43
+ end
44
+
45
+ it "must define a InputDir type" do
46
+ expect(subject.const_defined?('InputDir')).to be(true)
47
+ end
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-26 00:00:00.000000000 Z
11
+ date: 2021-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,6 +87,7 @@ files:
87
87
  - spec/types/num_spec.rb
88
88
  - spec/types/str_spec.rb
89
89
  - spec/types/type_spec.rb
90
+ - spec/types_spec.rb
90
91
  homepage: https://github.com/postmodern/command_mapper.rb#readme
91
92
  licenses:
92
93
  - MIT