hammer_cli 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/doc/creating_commands.md +15 -11
- data/doc/developer_docs.md +1 -0
- data/doc/option_normalizers.md +96 -0
- data/lib/hammer_cli/abstract.rb +0 -1
- data/lib/hammer_cli/apipie/command.rb +8 -12
- data/lib/hammer_cli/apipie/options.rb +16 -8
- data/lib/hammer_cli/apipie/resource.rb +3 -2
- data/lib/hammer_cli/main.rb +2 -2
- data/lib/hammer_cli/modules.rb +13 -1
- data/lib/hammer_cli/options/option_definition.rb +19 -0
- data/lib/hammer_cli/output/formatters.rb +11 -5
- data/lib/hammer_cli/validator.rb +2 -2
- data/lib/hammer_cli/version.rb +1 -1
- data/test/unit/abstract_test.rb +2 -2
- data/test/unit/apipie/command_test.rb +27 -23
- data/test/unit/modules_test.rb +72 -11
- data/test/unit/output/formatters_test.rb +12 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec98bfd08b8af7d5ec4dd2a7e7b215e1c3d348e4
|
4
|
+
data.tar.gz: 51fc2a97810bd8c8fed855eaee2b3b438b495a18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ea9c6240e80c754ee6391cb6be396527a720c7cf85e21b09d618e7cc35f9fdadd0765eac52f48656c819d60e03a3a46a0be7fc0b5cda538cd93c42db46c70f8
|
7
|
+
data.tar.gz: 176c84972b1b107252f2d93828596ff693f1b7156d8d920e5b58ec363cab85bee0e8fa777603a6b4fb4ed005b3cece2321cce25165d0b65a10ba006459ac47d5
|
data/doc/creating_commands.md
CHANGED
@@ -97,7 +97,9 @@ for the full list of available exit codes.
|
|
97
97
|
Our new command has only one option so far. It's `-h` which is built in for every command by default.
|
98
98
|
Option declaration is the same as in clamp so please read it's
|
99
99
|
[documentation](https://github.com/mdub/clamp/#declaring-options)
|
100
|
-
on that topic.
|
100
|
+
on that topic. However unlike in Clamp, the option accessors in Hammer are created with prefix 'option_', to avoid
|
101
|
+
conflict with methods of the commands. So to access value of an `--name` option you have to call `option_name()`
|
102
|
+
|
101
103
|
|
102
104
|
Example option usage could go like this:
|
103
105
|
```ruby
|
@@ -106,7 +108,7 @@ class HelloCommand < HammerCLI::AbstractCommand
|
|
106
108
|
option '--name', "NAME", "Name of the person you want to greet"
|
107
109
|
|
108
110
|
def execute
|
109
|
-
print_message "Hello %s!" % (
|
111
|
+
print_message "Hello %s!" % (option_name || "World")
|
110
112
|
HammerCLI::EX_OK
|
111
113
|
end
|
112
114
|
end
|
@@ -135,20 +137,20 @@ Hammer provides extended functionality for validating options.
|
|
135
137
|
First of all there is a dsl for validating combinations of options:
|
136
138
|
```ruby
|
137
139
|
validate_options do
|
138
|
-
all(:
|
139
|
-
option(:
|
140
|
+
all(:option_name, :option_surname).required # requires all the options
|
141
|
+
option(:option_age).required # requires a single option,
|
140
142
|
# equivalent of :required => true in option declaration
|
141
|
-
any(:
|
143
|
+
any(:option_email, :option_phone).required # requires at least one of the options
|
142
144
|
|
143
145
|
# Tt is possible to create more complicated constructs.
|
144
146
|
# This example requires either the full address or nothing
|
145
|
-
if any(:
|
146
|
-
all(:
|
147
|
+
if any(:option_street, :option_city, :option_zip).exist?
|
148
|
+
all(:option_street, :option_city, :option_zip).required
|
147
149
|
end
|
148
150
|
|
149
151
|
# Here you can reject all address related option when --no-address is passed
|
150
|
-
if option(:
|
151
|
-
all(:
|
152
|
+
if option(:option_no_address).exist?
|
153
|
+
all(:option_street, :option_city, :option_zip).rejected
|
152
154
|
end
|
153
155
|
end
|
154
156
|
|
@@ -159,6 +161,8 @@ Another option-related feature is a set of normalizers for specific option types
|
|
159
161
|
option values. Each normalizer has a description of the format it accepts. This description is printed
|
160
162
|
in commands' help.
|
161
163
|
|
164
|
+
See [our tutorial](option_normalizers.md#option-normalizers) if you want to create your custom normalizer.
|
165
|
+
|
162
166
|
##### _List_
|
163
167
|
|
164
168
|
Parses comma separated strings to a list of values.
|
@@ -220,7 +224,7 @@ module HammerCLIHello
|
|
220
224
|
option '--name', "NAME", "Name of the person you want to greet"
|
221
225
|
|
222
226
|
def execute
|
223
|
-
print_message "Hello %s!" % (name || "World")
|
227
|
+
print_message "Hello %s!" % (option_ name || "World")
|
224
228
|
HammerCLI::EX_OK
|
225
229
|
end
|
226
230
|
end
|
@@ -303,7 +307,7 @@ a message in a log for debugging purposes.
|
|
303
307
|
|
304
308
|
|
305
309
|
### Removing subcommands
|
306
|
-
If your plugin needs to disable existing subcommand, you can use `remove_subcommand` for this.
|
310
|
+
If your plugin needs to disable existing subcommand, you can use `remove_subcommand` for this.
|
307
311
|
|
308
312
|
```ruby
|
309
313
|
HammerCLI::MainCommand.remove_subcommand 'say'
|
data/doc/developer_docs.md
CHANGED
@@ -10,3 +10,4 @@ Contents:
|
|
10
10
|
- [Creating commands](creating_commands.md#create-your-first-command)
|
11
11
|
- [Creating ApiPie commands](creating_apipie_commands.md#creating-commands-for-restful-api-with-apipie)
|
12
12
|
- [Development tips](development_tips.md#development-tips)
|
13
|
+
- [Option normalizers](option_normalizers.md#option-normalizers)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
Option normalizers
|
2
|
+
------------------
|
3
|
+
|
4
|
+
The goal of option normalizers is to:
|
5
|
+
- provide description of valid option values
|
6
|
+
- check format and preprocess values passed by users
|
7
|
+
- offer value completion
|
8
|
+
|
9
|
+
Every normalizer must be descendant of `HammerCLI::Options::Normalizers::AbstractNormalizer`.
|
10
|
+
|
11
|
+
Example usage:
|
12
|
+
```ruby
|
13
|
+
option "--enabled", "ENABLED", "Should the host be enabled?",
|
14
|
+
:format => HammerCLI::Options::Normalizers::Bool.new
|
15
|
+
```
|
16
|
+
|
17
|
+
#### Description of valid values
|
18
|
+
There is method `description` that should return a help string. It's value is used in output of `-h`,
|
19
|
+
which can then look for example like this:
|
20
|
+
|
21
|
+
```
|
22
|
+
--enabled ENABLED Should the host be enabled?
|
23
|
+
One of true/false, yes/no, 1/0.
|
24
|
+
```
|
25
|
+
|
26
|
+
Abstract normalizer returns empty string by default.
|
27
|
+
|
28
|
+
|
29
|
+
#### Check and format passed values
|
30
|
+
|
31
|
+
Normalizer's method `format` is used for such checks. The method behaves as a filter taking
|
32
|
+
string value as it's input and returning value of any type.
|
33
|
+
|
34
|
+
If the value is not valid `ArgumentError` with an appropriate message should be risen.
|
35
|
+
Implementation in `Bool` normalizer is a good example of such functionality:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
def format(bool)
|
39
|
+
bool = bool.to_s
|
40
|
+
if bool.downcase.match(/^(true|t|yes|y|1)$/i)
|
41
|
+
return true
|
42
|
+
elsif bool.downcase.match(/^(false|f|no|n|0)$/i)
|
43
|
+
return false
|
44
|
+
else
|
45
|
+
raise ArgumentError, "value must be one of true/false, yes/no, 1/0"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
|
51
|
+
#### Value completion
|
52
|
+
|
53
|
+
Normalizers can also provide completion of option values via method `complete`. It takes one argument - current option value at the time the completion was requested. In the simplest cases the method returns array of all possible values. More complex completions can use the current value argument for building the return values.
|
54
|
+
|
55
|
+
We distinguish two types of offered completion strings:
|
56
|
+
|
57
|
+
**Terminal completions**
|
58
|
+
- used in most cases
|
59
|
+
- the value is terminal and the completion finishes when it is selected
|
60
|
+
- terminal strings have to end with a blank space
|
61
|
+
|
62
|
+
**Partial complations**
|
63
|
+
- used to offer completion pieces, eg. directory names when completing file path
|
64
|
+
- the completion continues until a terminal string is selected
|
65
|
+
- the values have to end with any character but blank space
|
66
|
+
|
67
|
+
Completing file paths demonstrate the difference nicely:
|
68
|
+
```ruby
|
69
|
+
# "hammer some command --file /etc/f"
|
70
|
+
file_normalizer.complete("/etc/f")
|
71
|
+
[
|
72
|
+
"/etc/foreman/", # partial completion, can continue with the directory contents
|
73
|
+
"/etc/foo/", # -- || --
|
74
|
+
"/etc/foo.conf " # terminal, the completion can't continue
|
75
|
+
]
|
76
|
+
```
|
77
|
+
Example of a simple completion method for boolean values:
|
78
|
+
```ruby
|
79
|
+
def complete(value)
|
80
|
+
["yes ", "no "]
|
81
|
+
end
|
82
|
+
```
|
83
|
+
Example of a method completing file paths:
|
84
|
+
```ruby
|
85
|
+
def complete(value)
|
86
|
+
Dir[value.to_s+'*'].collect do |file|
|
87
|
+
if ::File.directory?(file)
|
88
|
+
file+'/'
|
89
|
+
else
|
90
|
+
file+' '
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
See more examples in [normalizers.rb](../lib/hammer_cli/options/normalizers.rb).
|
data/lib/hammer_cli/abstract.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../abstract')
|
1
2
|
require File.join(File.dirname(__FILE__), 'options')
|
2
3
|
require File.join(File.dirname(__FILE__), 'resource')
|
3
4
|
|
@@ -8,24 +9,13 @@ module HammerCLI::Apipie
|
|
8
9
|
include HammerCLI::Apipie::Resource
|
9
10
|
include HammerCLI::Apipie::Options
|
10
11
|
|
11
|
-
def initialize(*args)
|
12
|
-
super
|
13
|
-
setup_identifier_options
|
14
|
-
end
|
15
|
-
|
16
|
-
def setup_identifier_options
|
17
|
-
self.class.identifier_option(:id, "resource id")
|
18
|
-
self.class.identifier_option(:name, "resource name")
|
19
|
-
self.class.identifier_option(:label, "resource label")
|
20
|
-
end
|
21
|
-
|
22
12
|
def self.identifiers(*keys)
|
23
13
|
@identifiers ||= {}
|
24
14
|
keys.each do |key|
|
25
15
|
if key.is_a? Hash
|
26
16
|
@identifiers.merge!(key)
|
27
17
|
else
|
28
|
-
@identifiers.update(key => key)
|
18
|
+
@identifiers.update(key => HammerCLI.option_accessor_name(key))
|
29
19
|
end
|
30
20
|
end
|
31
21
|
end
|
@@ -74,6 +64,12 @@ module HammerCLI::Apipie
|
|
74
64
|
|
75
65
|
private
|
76
66
|
|
67
|
+
def self.setup_identifier_options
|
68
|
+
identifier_option(:id, "resource id")
|
69
|
+
identifier_option(:name, "resource name")
|
70
|
+
identifier_option(:label, "resource label")
|
71
|
+
end
|
72
|
+
|
77
73
|
def self.identifier_option(name, desc)
|
78
74
|
attr_name = declared_identifiers[name]
|
79
75
|
option "--"+name.to_s, name.to_s.upcase, desc, :attribute_name => attr_name if self.identifier? name
|
@@ -19,25 +19,33 @@ module HammerCLI::Apipie
|
|
19
19
|
params.each do |p|
|
20
20
|
if p["expected_type"] == "hash"
|
21
21
|
opts[p["name"]] = method_options_for_params(p["params"], include_nil)
|
22
|
-
elsif respond_to?(p["name"], true)
|
23
|
-
opts[p["name"]] = send(p["name"])
|
24
22
|
else
|
25
|
-
opts[p["name"]] =
|
23
|
+
opts[p["name"]] = get_option_value(p["name"])
|
26
24
|
end
|
27
25
|
end
|
28
26
|
opts.reject! {|key, value| value.nil? } unless include_nil
|
29
27
|
opts
|
30
28
|
end
|
31
29
|
|
30
|
+
def get_option_value(opt_name)
|
31
|
+
if respond_to?(HammerCLI.option_accessor_name(opt_name), true)
|
32
|
+
send(HammerCLI.option_accessor_name(opt_name))
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
32
38
|
module ClassMethods
|
33
39
|
|
34
40
|
def apipie_options(options={})
|
35
|
-
|
41
|
+
setup_identifier_options
|
42
|
+
if resource_defined?
|
43
|
+
filter = options[:without] || []
|
44
|
+
filter = Array(filter)
|
45
|
+
filter += declared_identifiers.keys
|
36
46
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
options_for_params(resource.docs_for(action)["params"], filter)
|
47
|
+
options_for_params(resource.docs_for(action)["params"], filter)
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
protected
|
@@ -33,9 +33,9 @@ module HammerCLI::Apipie
|
|
33
33
|
self.new(definition.resource_class, config)
|
34
34
|
end
|
35
35
|
|
36
|
-
def call(method_name, params=nil)
|
36
|
+
def call(method_name, params=nil, headers=nil)
|
37
37
|
Logging.logger[resource_class.name].debug "Calling '#{method_name}' with params #{params.ai}" if HammerCLI::Settings.get(:log_api_calls)
|
38
|
-
result = instance.send(method_name, params)
|
38
|
+
result = instance.send(method_name, params, headers)
|
39
39
|
Logging.logger[resource_class.name].debug "Method '#{method_name}' responded with #{result[0].ai}" if HammerCLI::Settings.get(:log_api_calls)
|
40
40
|
result
|
41
41
|
end
|
@@ -83,6 +83,7 @@ module HammerCLI::Apipie
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def module_resource
|
86
|
+
return nil unless self.name
|
86
87
|
enclosing_module = self.name.split("::")[0..-2].inject(Object) { |mod, cls| mod.const_get cls }
|
87
88
|
|
88
89
|
if enclosing_module.respond_to? :resource
|
data/lib/hammer_cli/main.rb
CHANGED
@@ -27,7 +27,7 @@ module HammerCLI
|
|
27
27
|
:format => HammerCLI::Options::Normalizers::Bool.new,
|
28
28
|
:context_target => :interactive
|
29
29
|
|
30
|
-
option ["--csv"], :flag, "Output as CSV (same as --
|
30
|
+
option ["--csv"], :flag, "Output as CSV (same as --output=csv)"
|
31
31
|
option ["--output"], "ADAPTER", "Set output format. One of [%s]" %
|
32
32
|
HammerCLI::Output::Output.adapters.keys.join(', '),
|
33
33
|
:context_target => :adapter
|
@@ -44,7 +44,7 @@ module HammerCLI
|
|
44
44
|
exit(HammerCLI::EX_OK)
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
47
|
+
def option_csv=(csv)
|
48
48
|
context[:adapter] = :csv
|
49
49
|
end
|
50
50
|
|
data/lib/hammer_cli/modules.rb
CHANGED
@@ -19,16 +19,28 @@ module HammerCLI
|
|
19
19
|
return nil
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.load(name)
|
22
|
+
def self.load!(name)
|
23
23
|
begin
|
24
24
|
require_module(name)
|
25
|
+
rescue LoadError => e
|
26
|
+
logger.error "Module #{name} not found"
|
27
|
+
raise e
|
25
28
|
rescue Exception => e
|
26
29
|
logger.error "Error while loading module #{name}"
|
30
|
+
logger.error e
|
31
|
+
puts "Warning: An error occured while loading module #{name}"
|
27
32
|
raise e
|
28
33
|
end
|
29
34
|
|
30
35
|
version = find_by_name(name).version
|
31
36
|
logger.info "Extension module #{name} (#{version}) loaded"
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.load(name)
|
41
|
+
load! name
|
42
|
+
rescue Exception => e
|
43
|
+
false
|
32
44
|
end
|
33
45
|
|
34
46
|
def self.require_module(name)
|
@@ -1,6 +1,19 @@
|
|
1
1
|
require 'clamp'
|
2
2
|
|
3
3
|
module HammerCLI
|
4
|
+
|
5
|
+
def self.option_accessor_name(*name)
|
6
|
+
if name.length > 1
|
7
|
+
name.map { |n| _option_accessor_name(n) }
|
8
|
+
else
|
9
|
+
_option_accessor_name(name.first)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self._option_accessor_name(name)
|
14
|
+
"option_#{name.to_s}".gsub('-', '_')
|
15
|
+
end
|
16
|
+
|
4
17
|
module Options
|
5
18
|
|
6
19
|
class OptionDefinition < Clamp::Option::Definition
|
@@ -71,6 +84,12 @@ module HammerCLI
|
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
87
|
+
private
|
88
|
+
|
89
|
+
def infer_attribute_name
|
90
|
+
HammerCLI.option_accessor_name(super)
|
91
|
+
end
|
92
|
+
|
74
93
|
end
|
75
94
|
|
76
95
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module HammerCLI::Output
|
2
2
|
module Formatters
|
3
3
|
|
4
|
-
# Registry for formatters
|
4
|
+
# Registry for formatters
|
5
5
|
class FormatterLibrary
|
6
6
|
def initialize(formatter_map={})
|
7
7
|
|
8
8
|
@_formatters = {}
|
9
|
-
formatter_map.each do |type, formatters|
|
9
|
+
formatter_map.each do |type, formatters|
|
10
10
|
register_formatter(type, *Array(formatters))
|
11
11
|
end
|
12
12
|
end
|
@@ -14,7 +14,7 @@ module HammerCLI::Output
|
|
14
14
|
def register_formatter(type, *formatters)
|
15
15
|
if @_formatters[type].nil?
|
16
16
|
@_formatters[type] = FormatterContainer.new *formatters
|
17
|
-
else
|
17
|
+
else
|
18
18
|
formatters.each { |f| @_formatters[type].add_formatter(f) }
|
19
19
|
end
|
20
20
|
end
|
@@ -30,7 +30,7 @@ module HammerCLI::Output
|
|
30
30
|
# as we expect them to serialize the value.
|
31
31
|
#
|
32
32
|
# - by format: :flat x :data
|
33
|
-
# - by output: :file X :screen
|
33
|
+
# - by output: :file X :screen
|
34
34
|
|
35
35
|
# abstract formatter
|
36
36
|
class FieldFormatter
|
@@ -99,7 +99,13 @@ module HammerCLI::Output
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def format(list)
|
102
|
-
list.
|
102
|
+
if list.is_a? Array
|
103
|
+
list.join(", ")
|
104
|
+
elsif list
|
105
|
+
list.to_s
|
106
|
+
else
|
107
|
+
""
|
108
|
+
end
|
103
109
|
end
|
104
110
|
end
|
105
111
|
|
data/lib/hammer_cli/validator.rb
CHANGED
@@ -94,7 +94,7 @@ module HammerCLI
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def all(*to_check)
|
97
|
-
AllConstraint.new(@options, to_check)
|
97
|
+
AllConstraint.new(@options, to_check.flatten(1))
|
98
98
|
end
|
99
99
|
|
100
100
|
def option(to_check)
|
@@ -102,7 +102,7 @@ module HammerCLI
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def any(*to_check)
|
105
|
-
AnyConstraint.new(@options, to_check)
|
105
|
+
AnyConstraint.new(@options, to_check.flatten(1))
|
106
106
|
end
|
107
107
|
|
108
108
|
def run(&block)
|
data/lib/hammer_cli/version.rb
CHANGED
data/test/unit/abstract_test.rb
CHANGED
@@ -101,7 +101,7 @@ describe HammerCLI::AbstractCommand do
|
|
101
101
|
test_command_class.option(['--password'], 'PASSWORD', 'Password')
|
102
102
|
test_command = test_command_class.new("")
|
103
103
|
test_command.run ['--password=pass']
|
104
|
-
@log_output.readline.strip.must_equal "INFO HammerCLI::AbstractCommand : Called with options: {\"
|
104
|
+
@log_output.readline.strip.must_equal "INFO HammerCLI::AbstractCommand : Called with options: {\"option_password\"=>\"***\"}"
|
105
105
|
end
|
106
106
|
|
107
107
|
class TestLogCmd < HammerCLI::AbstractCommand
|
@@ -282,7 +282,7 @@ describe HammerCLI::AbstractCommand do
|
|
282
282
|
class CmdOD1 < HammerCLI::AbstractCommand
|
283
283
|
output do
|
284
284
|
label 'Label' do
|
285
|
-
end
|
285
|
+
end
|
286
286
|
end
|
287
287
|
end
|
288
288
|
|
@@ -30,50 +30,52 @@ describe HammerCLI::Apipie::Command do
|
|
30
30
|
|
31
31
|
class Cmd1 < HammerCLI::Apipie::Command
|
32
32
|
identifiers :id, :name, :label
|
33
|
+
apipie_options
|
33
34
|
end
|
34
35
|
|
35
36
|
class Cmd2 < Cmd1
|
36
37
|
identifiers :id
|
38
|
+
apipie_options
|
37
39
|
end
|
38
40
|
|
39
41
|
it "must not set any option by default" do
|
40
|
-
|
42
|
+
cmd_class.apipie_options
|
41
43
|
cmd_class.declared_options.must_equal []
|
42
44
|
end
|
43
45
|
|
44
46
|
it "can set option --id" do
|
45
47
|
cmd_class.identifiers :id
|
46
|
-
|
48
|
+
cmd_class.apipie_options
|
47
49
|
option_switches.must_equal [["--id"]]
|
48
|
-
option_attribute_names.must_equal ["id"]
|
50
|
+
option_attribute_names.must_equal [HammerCLI.option_accessor_name("id")]
|
49
51
|
end
|
50
52
|
|
51
53
|
it "can set option --name" do
|
52
54
|
cmd_class.identifiers :name
|
53
|
-
|
55
|
+
cmd_class.apipie_options
|
54
56
|
option_switches.must_equal [["--name"]]
|
55
|
-
option_attribute_names.must_equal ["name"]
|
57
|
+
option_attribute_names.must_equal [HammerCLI.option_accessor_name("name")]
|
56
58
|
end
|
57
59
|
|
58
60
|
it "can set option --label" do
|
59
61
|
cmd_class.identifiers :label
|
60
|
-
|
62
|
+
cmd_class.apipie_options
|
61
63
|
option_switches.must_equal [["--label"]]
|
62
|
-
option_attribute_names.must_equal ["label"]
|
64
|
+
option_attribute_names.must_equal [HammerCLI.option_accessor_name("label")]
|
63
65
|
end
|
64
66
|
|
65
67
|
it "can set multiple identifiers" do
|
66
68
|
cmd_class.identifiers :id, :name, :label
|
67
|
-
|
69
|
+
cmd_class.apipie_options
|
68
70
|
option_switches.must_equal [["--id"], ["--label"], ["--name"]]
|
69
|
-
option_attribute_names.must_equal
|
71
|
+
option_attribute_names.must_equal HammerCLI.option_accessor_name("id", "label", "name")
|
70
72
|
end
|
71
73
|
|
72
74
|
it "can change option reader" do
|
73
|
-
cmd_class.identifiers :name, :id => :
|
74
|
-
|
75
|
+
cmd_class.identifiers :name, :id => :option_id_read_method
|
76
|
+
cmd_class.apipie_options
|
75
77
|
option_switches.must_equal [["--id"], ["--name"]]
|
76
|
-
option_attribute_names.must_equal
|
78
|
+
option_attribute_names.must_equal HammerCLI.option_accessor_name("id_read_method", "name")
|
77
79
|
end
|
78
80
|
|
79
81
|
it "can override inentifiers in inherrited classes" do
|
@@ -84,11 +86,13 @@ describe HammerCLI::Apipie::Command do
|
|
84
86
|
|
85
87
|
it "must require one of declared identifiers" do
|
86
88
|
cmd_class.identifiers :id, :name
|
89
|
+
cmd_class.apipie_options
|
87
90
|
cmd.run(["--id=1"]).must_equal HammerCLI::EX_OK
|
88
91
|
end
|
89
92
|
|
90
93
|
it "must raise exception when no attribute is passed" do
|
91
94
|
cmd_class.identifiers :id, :name
|
95
|
+
cmd_class.apipie_options
|
92
96
|
cmd.run([]).must_equal HammerCLI::EX_USAGE
|
93
97
|
end
|
94
98
|
|
@@ -172,7 +176,7 @@ describe HammerCLI::Apipie::Command do
|
|
172
176
|
end
|
173
177
|
|
174
178
|
it "should set correct attribute name" do
|
175
|
-
option.attribute_name.must_equal 'se_arch_val_ue'
|
179
|
+
option.attribute_name.must_equal HammerCLI.option_accessor_name('se_arch_val_ue')
|
176
180
|
end
|
177
181
|
|
178
182
|
it "should set description with html tags stripped" do
|
@@ -189,7 +193,7 @@ describe HammerCLI::Apipie::Command do
|
|
189
193
|
let(:required_options) { cmd_class.declared_options.reject{|opt| !opt.required?} }
|
190
194
|
|
191
195
|
it "should set required flag for the required options" do
|
192
|
-
required_options.map(&:attribute_name).sort.must_equal ["array_param"]
|
196
|
+
required_options.map(&:attribute_name).sort.must_equal [HammerCLI.option_accessor_name("array_param")]
|
193
197
|
end
|
194
198
|
end
|
195
199
|
|
@@ -200,11 +204,11 @@ describe HammerCLI::Apipie::Command do
|
|
200
204
|
end
|
201
205
|
|
202
206
|
it "should create options for all parameters except the hash" do
|
203
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal
|
207
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal HammerCLI.option_accessor_name("array_param", "name", "provider")
|
204
208
|
end
|
205
209
|
|
206
210
|
it "should name the options correctly" do
|
207
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal
|
211
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal HammerCLI.option_accessor_name("array_param", "name", "provider")
|
208
212
|
end
|
209
213
|
end
|
210
214
|
|
@@ -222,17 +226,17 @@ describe HammerCLI::Apipie::Command do
|
|
222
226
|
|
223
227
|
it "should parse comma separated string to array" do
|
224
228
|
cmd.run(["--array-param=valA,valB,valC"])
|
225
|
-
cmd.array_param.must_equal ['valA', 'valB', 'valC']
|
229
|
+
cmd.get_option_value(:array_param).must_equal ['valA', 'valB', 'valC']
|
226
230
|
end
|
227
231
|
|
228
232
|
it "should parse string to array of length 1" do
|
229
233
|
cmd.run(["--array-param=valA"])
|
230
|
-
cmd.array_param.must_equal ['valA']
|
234
|
+
cmd.get_option_value(:array_param).must_equal ['valA']
|
231
235
|
end
|
232
236
|
|
233
237
|
it "should parse empty string to empty array" do
|
234
238
|
cmd.run(['--array-param='])
|
235
|
-
cmd.array_param.must_equal []
|
239
|
+
cmd.get_option_value(:array_param).must_equal []
|
236
240
|
end
|
237
241
|
|
238
242
|
end
|
@@ -245,22 +249,22 @@ describe HammerCLI::Apipie::Command do
|
|
245
249
|
|
246
250
|
it "should skip filtered options" do
|
247
251
|
cmd_class.apipie_options :without => ["provider", "name"]
|
248
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal ["array_param"]
|
252
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal [HammerCLI.option_accessor_name("array_param")]
|
249
253
|
end
|
250
254
|
|
251
255
|
it "should skip filtered options defined as symbols" do
|
252
256
|
cmd_class.apipie_options :without => [:provider, :name]
|
253
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal ["array_param"]
|
257
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal [HammerCLI.option_accessor_name("array_param")]
|
254
258
|
end
|
255
259
|
|
256
260
|
it "should skip single filtered option in array" do
|
257
261
|
cmd_class.apipie_options :without => ["provider"]
|
258
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal
|
262
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal HammerCLI.option_accessor_name("array_param", "name")
|
259
263
|
end
|
260
264
|
|
261
265
|
it "should skip single filtered option" do
|
262
266
|
cmd_class.apipie_options :without => "provider"
|
263
|
-
cmd_class.declared_options.map(&:attribute_name).sort.must_equal
|
267
|
+
cmd_class.declared_options.map(&:attribute_name).sort.must_equal HammerCLI.option_accessor_name("array_param", "name")
|
264
268
|
end
|
265
269
|
|
266
270
|
end
|
data/test/unit/modules_test.rb
CHANGED
@@ -61,22 +61,83 @@ describe HammerCLI::Modules do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
describe "load a module" do
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
describe "success" do
|
65
|
+
before :each do
|
66
|
+
HammerCLI::Modules.stubs(:require_module)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "must require a module" do
|
70
|
+
HammerCLI::Modules.expects(:require_module).with("hammer_cli_tom")
|
71
|
+
HammerCLI::Modules.load("hammer_cli_tom")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "must log module's name and version" do
|
75
|
+
HammerCLI::Modules.expects(:require_module).with("hammer_cli_tom")
|
76
|
+
HammerCLI::Modules.load("hammer_cli_tom")
|
77
|
+
@log_output.readline.strip.must_equal "INFO Modules : Extension module hammer_cli_tom (0.0.1) loaded"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "must return true when load succeeds" do
|
81
|
+
HammerCLI::Modules.load("hammer_cli_tom").must_equal true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "must return true when load! succeeds" do
|
85
|
+
HammerCLI::Modules.load!("hammer_cli_tom").must_equal true
|
86
|
+
end
|
67
87
|
end
|
68
88
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
89
|
+
describe "module not found" do
|
90
|
+
before :each do
|
91
|
+
HammerCLI::Modules.stubs(:require_module).raises(LoadError)
|
92
|
+
@error_msg = "ERROR Modules : Module hammer_cli_tom not found"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "must log an error if the load! fails" do
|
96
|
+
proc { HammerCLI::Modules.load!("hammer_cli_tom") }.must_raise LoadError
|
97
|
+
@log_output.readline.strip.must_equal @error_msg
|
98
|
+
end
|
99
|
+
|
100
|
+
it "must log an error if the load fails" do
|
101
|
+
HammerCLI::Modules.load("hammer_cli_tom")
|
102
|
+
@log_output.readline.strip.must_equal @error_msg
|
103
|
+
end
|
104
|
+
|
105
|
+
it "must return false when load fails" do
|
106
|
+
HammerCLI::Modules.load("hammer_cli_tom").must_equal false
|
107
|
+
end
|
73
108
|
end
|
74
|
-
end
|
75
109
|
|
76
|
-
|
77
|
-
|
78
|
-
|
110
|
+
describe "module runtime exception" do
|
111
|
+
before :each do
|
112
|
+
HammerCLI::Modules.stubs(:require_module).raises(RuntimeError)
|
113
|
+
@error_msg = "ERROR Modules : Error while loading module hammer_cli_tom"
|
114
|
+
@warning_msg = "Warning: An error occured while loading module hammer_cli_tom"
|
115
|
+
end
|
116
|
+
|
117
|
+
it "must log an error if the load! fails" do
|
118
|
+
proc {
|
119
|
+
proc {
|
120
|
+
HammerCLI::Modules.load!("hammer_cli_tom")
|
121
|
+
}.must_output("#{@warning_msg}\n", "")
|
122
|
+
}.must_raise RuntimeError
|
123
|
+
@log_output.readline.strip.must_equal @error_msg
|
124
|
+
end
|
125
|
+
|
126
|
+
it "must log an error if the load fails" do
|
127
|
+
proc {
|
128
|
+
HammerCLI::Modules.load("hammer_cli_tom")
|
129
|
+
}.must_output("#{@warning_msg}\n", "")
|
130
|
+
@log_output.readline.strip.must_equal @error_msg
|
131
|
+
end
|
132
|
+
|
133
|
+
it "must return false when load fails" do
|
134
|
+
proc {
|
135
|
+
HammerCLI::Modules.load("hammer_cli_tom").must_equal false
|
136
|
+
}.must_output("#{@warning_msg}\n", "")
|
137
|
+
end
|
79
138
|
end
|
80
139
|
|
140
|
+
end
|
141
|
+
|
81
142
|
end
|
82
143
|
|
@@ -43,7 +43,7 @@ describe HammerCLI::Output::Formatters::FormatterContainer do
|
|
43
43
|
container = HammerCLI::Output::Formatters::FormatterContainer.new(TestFormatter.new)
|
44
44
|
container.format('').must_equal '.'
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "has format method" do
|
48
48
|
container = HammerCLI::Output::Formatters::FormatterContainer.new
|
49
49
|
container.respond_to?(:format).must_equal true
|
@@ -72,7 +72,7 @@ describe HammerCLI::Output::Formatters::DateFormatter do
|
|
72
72
|
it "returns empty string on wrong value" do
|
73
73
|
formatter = HammerCLI::Output::Formatters::DateFormatter.new
|
74
74
|
formatter.format('wrong value').must_equal ""
|
75
|
-
end
|
75
|
+
end
|
76
76
|
end
|
77
77
|
|
78
78
|
describe HammerCLI::Output::Formatters::ListFormatter do
|
@@ -80,4 +80,14 @@ describe HammerCLI::Output::Formatters::ListFormatter do
|
|
80
80
|
formatter = HammerCLI::Output::Formatters::ListFormatter.new
|
81
81
|
formatter.format([1, 2]).must_equal '1, 2'
|
82
82
|
end
|
83
|
+
|
84
|
+
it "returns empty string when the input is nil" do
|
85
|
+
formatter = HammerCLI::Output::Formatters::ListFormatter.new
|
86
|
+
formatter.format(nil).must_equal ''
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns string value when the input is not a list" do
|
90
|
+
formatter = HammerCLI::Output::Formatters::ListFormatter.new
|
91
|
+
formatter.format('some string').must_equal 'some string'
|
92
|
+
end
|
83
93
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hammer_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Bačovský
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: clamp
|
@@ -134,6 +134,7 @@ extra_rdoc_files:
|
|
134
134
|
- doc/development_tips.md
|
135
135
|
- doc/developer_docs.md
|
136
136
|
- doc/creating_commands.md
|
137
|
+
- doc/option_normalizers.md
|
137
138
|
- doc/design.png
|
138
139
|
- doc/design.uml
|
139
140
|
- doc/writing_a_plugin.md
|
@@ -206,6 +207,7 @@ files:
|
|
206
207
|
- doc/development_tips.md
|
207
208
|
- doc/developer_docs.md
|
208
209
|
- doc/creating_commands.md
|
210
|
+
- doc/option_normalizers.md
|
209
211
|
- doc/design.png
|
210
212
|
- doc/design.uml
|
211
213
|
- doc/writing_a_plugin.md
|