sleeping_king_studios-tasks 0.2.0 → 0.3.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: cc8e07d6f211c9e3dbf15ddc93b851b6b27114987be947ee082ed67271997d47
4
- data.tar.gz: b33121e54e1c6ce5d4c76b03e205985bcee11d551dc958f00acc73fc81b40eb8
3
+ metadata.gz: c9380cfb581917cac00ae5102325dd895fcbd1364b4d8a53844f9ead55a41173
4
+ data.tar.gz: 69647411117043bf53bf24c4f47231de7d970de6c3adff412cc4a5228af7939e
5
5
  SHA512:
6
- metadata.gz: 78f51530a5a325edcd1fca06464a01424fcce2de696e5d365d961bc8a871bfdde893c33b0d230cd1ff8fa67384ef269fdab25618582d98287f6e4c68d8d88366
7
- data.tar.gz: b5c7433200eb5c7fb91530136405d52b739491f953aeabc438e8c0d4b5cdbb29003c824a37e1c43deda991624c9e546997e83893751c2996a94d68c065653046
6
+ metadata.gz: 563983af6ab016118a21b810e8c5b2f61ef915ddee3bdce425f8945c5bf2bfb5dfc21a14acf8a07a7c08776443fd0cf7e46e5f96ff2c708a88f0834e4d856e51
7
+ data.tar.gz: 0b2d75151cc7513903514ed8f60041c5b7e73b2723373ceedb7f904a65059e8815f100f9cb54f745c6619274650f3ca7b2da063b50082b5548159fcf0d3918d9
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0
4
+
5
+ - Fix deprecation warnings in Ruby 2.7.
6
+ - Add support for Thor 1.0.
7
+
3
8
  ## 0.2.0
4
9
 
5
10
  ### Ci
@@ -29,8 +29,8 @@ module SleepingKingStudios::Tasks
29
29
  end # method base_command
30
30
 
31
31
  def build_command **kwargs
32
- env = build_environment(kwargs)
33
- opts = build_options(kwargs)
32
+ env = build_environment(**kwargs)
33
+ opts = build_options(**kwargs)
34
34
 
35
35
  "#{env} #{base_command} #{opts}".strip
36
36
  end # method build_command
@@ -52,7 +52,7 @@ module SleepingKingStudios::Tasks
52
52
  end # method build_options
53
53
 
54
54
  def stream_process command
55
- Bundler.with_clean_env do
55
+ unbundled_env do
56
56
  IO.popen(command) do |io|
57
57
  loop do
58
58
  char = io.getc
@@ -60,11 +60,21 @@ module SleepingKingStudios::Tasks
60
60
  char ? print(char) : break
61
61
  end # loop
62
62
  end # popen
63
- end # with_clean_env
63
+ end # with_unbundled_env
64
64
  end # method stream_process
65
65
 
66
66
  def tools
67
67
  SleepingKingStudios::Tools::Toolbelt.new
68
68
  end # method tools
69
+
70
+ def unbundled_env
71
+ # :nocov:
72
+ if Bundler.respond_to?(:with_unbundled_env)
73
+ Bundler.with_unbundled_env { yield }
74
+ else
75
+ Bundler.with_clean_env { yield }
76
+ end
77
+ # :nocov:
78
+ end
69
79
  end # class
70
80
  end # module
@@ -11,7 +11,7 @@ module SleepingKingStudios
11
11
  # Major version.
12
12
  MAJOR = 0
13
13
  # Minor version.
14
- MINOR = 2
14
+ MINOR = 3
15
15
  # Patch version.
16
16
  PATCH = 0
17
17
  # Prerelease version.
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sleeping_king_studios/tools/core_tools'
4
+ require 'sleeping_king_studios/tools/toolbox'
5
+
6
+ # :nocov:
7
+ module SleepingKingStudios::Tools::Toolbox
8
+ # Abstract base class for defining configuration objects.
9
+ class Configuration # rubocop:disable Metrics/ClassLength
10
+ # Class methods for configuration objects.
11
+ module ClassMethods
12
+ DEFAULT_OPTION = Object.new.freeze
13
+
14
+ # Defines a nested namespace for the configuration object.
15
+ #
16
+ # A namespace is represented by a nested configuration object, which has
17
+ # its own options and namespaces.
18
+ #
19
+ # @param namespace_name [String] The name of the namespace.
20
+ #
21
+ # @yield namespace If a block is given, that block will be executed in the
22
+ # context of the newly created namespace.
23
+ #
24
+ # @return [Configuration] the created namespace object.
25
+ def namespace(namespace_name, &block)
26
+ guard_abstract_class!
27
+
28
+ namespace =
29
+ (@namespaces ||= {}).fetch(namespace_name) do
30
+ @namespaces[namespace_name] = define_namespace namespace_name
31
+ end
32
+
33
+ namespace.instance_exec(namespace, &block) if block_given?
34
+
35
+ namespace
36
+ end
37
+
38
+ # Defines an option for the configuration object.
39
+ #
40
+ # A configuration option has a name and a value. It can be defined with a
41
+ # default value, or to allow or prohibit nil values or restrict possible
42
+ # values to a given set.
43
+ #
44
+ # @param option_name [String] The name of the option.
45
+ # @param allow_nil [true, false] If false, setting the option value to nil
46
+ # or an empty value will raise an error, as will trying to access the
47
+ # value when it has not been set. Defaults to false.
48
+ # @param default [Object] The default value for the option. If this is not
49
+ # set, the default value for the option will be nil.
50
+ # @param enum [Array] An enumerable list of valid values for the option.
51
+ def option(
52
+ option_name,
53
+ allow_nil: false,
54
+ default: DEFAULT_OPTION,
55
+ enum: nil
56
+ )
57
+ guard_abstract_class!
58
+
59
+ options = {
60
+ allow_nil: allow_nil,
61
+ default: default,
62
+ enum: enum
63
+ }
64
+
65
+ define_option_accessor option_name, options
66
+ define_option_mutator option_name, options
67
+
68
+ option_name.intern
69
+ end
70
+
71
+ private
72
+
73
+ def define_namespace(namespace_name)
74
+ namespace =
75
+ Class.new(SleepingKingStudios::Tools::Toolbox::Configuration)
76
+
77
+ define_namespace_accessor(namespace_name, namespace)
78
+
79
+ namespace
80
+ end
81
+
82
+ def define_namespace_accessor(namespace_name, namespace_class)
83
+ namespace_ivar = :"@#{namespace_name}"
84
+
85
+ define_method namespace_name do |&block|
86
+ if instance_variable_defined?(namespace_ivar)
87
+ return instance_variable_get(namespace_ivar).tap do |config|
88
+ block&.call(config)
89
+ end
90
+ end
91
+
92
+ initialize_namespace(namespace_name, namespace_class, &block)
93
+ end
94
+ end
95
+
96
+ def define_option_accessor(option_name, options)
97
+ define_method option_name do
98
+ get_value(option_name, options)
99
+ end
100
+ end
101
+
102
+ def define_option_mutator(option_name, options)
103
+ writer_name = :"#{option_name}="
104
+
105
+ define_method writer_name do |value|
106
+ set_value(option_name, value, options)
107
+ end
108
+ end
109
+
110
+ def guard_abstract_class!
111
+ return unless self == SleepingKingStudios::Tools::Toolbox::Configuration
112
+
113
+ raise "can't define namespace or option on abstract class"
114
+ end
115
+ end
116
+ extend ClassMethods
117
+
118
+ DEFAULT_OPTION = ClassMethods::DEFAULT_OPTION
119
+
120
+ # @param data [Hash, Object] The data source used to populate configuration
121
+ # values. Can be a Hash or a data object. If the data source is nil, or no
122
+ # data source is given, values will be set to their respective defaults.
123
+ #
124
+ # @yieldparam [Class] The singleton class of the new configuration object.
125
+ def initialize(data = nil)
126
+ @data = convert_data_to_struct(data)
127
+ @root_namespace = self
128
+
129
+ return unless block_given?
130
+
131
+ SleepingKingStudios::Tools::CoreTools
132
+ .deprecate('Configuration#initialize with a block')
133
+
134
+ yield(singleton_class)
135
+ end
136
+
137
+ def [](key)
138
+ send(key) if respond_to?(key)
139
+ end
140
+
141
+ def []=(key, value)
142
+ send(:"#{key}=", value) if respond_to?(key)
143
+ end
144
+
145
+ def dig(*keys)
146
+ keys.reduce(self) do |config, key|
147
+ value = config[key]
148
+
149
+ return value if value.nil?
150
+
151
+ value
152
+ end
153
+ end
154
+
155
+ def fetch(key, default = DEFAULT_OPTION)
156
+ return send(key) if respond_to?(key)
157
+
158
+ return default unless default == DEFAULT_OPTION
159
+
160
+ return yield(key) if block_given?
161
+
162
+ raise KeyError, "key not found: #{key.inspect}"
163
+ end
164
+
165
+ protected
166
+
167
+ attr_accessor :root_namespace
168
+
169
+ private
170
+
171
+ attr_reader :data
172
+
173
+ def blank_value?(value)
174
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
175
+ end
176
+
177
+ def convert_data_to_struct(data)
178
+ return data unless data.is_a?(Hash)
179
+
180
+ return Object.new if data.empty?
181
+
182
+ obj = Struct.new(*data.keys).new
183
+
184
+ data.each do |key, value|
185
+ val = value.is_a?(Hash) ? convert_data_to_struct(value) : value
186
+
187
+ obj.send :"#{key}=", val
188
+ end
189
+
190
+ obj
191
+ end
192
+
193
+ def evaluate_default(default)
194
+ return default unless default.is_a?(Proc)
195
+
196
+ root_namespace.instance_exec(&default)
197
+ end
198
+
199
+ def get_default_value(options)
200
+ value = evaluate_default(options[:default])
201
+
202
+ validate_value value, options
203
+
204
+ value
205
+ end
206
+
207
+ def get_method_value(name, options)
208
+ value = data.send(name)
209
+
210
+ if value.nil? && options[:default] != DEFAULT_OPTION
211
+ value = evaluate_default(options[:default])
212
+ end
213
+
214
+ validate_value(value, options)
215
+
216
+ value
217
+ end
218
+
219
+ def get_value(name, options)
220
+ if data.respond_to?(name)
221
+ get_method_value(name, options)
222
+ elsif instance_variable_defined?(:"@#{name}")
223
+ instance_variable_get(:"@#{name}")
224
+ elsif options[:default] != DEFAULT_OPTION
225
+ get_default_value(options)
226
+ else
227
+ validate_value(nil, options)
228
+
229
+ nil
230
+ end
231
+ end
232
+
233
+ def initialize_namespace(namespace_name, namespace_class, &block)
234
+ data = get_value(namespace_name, default: Object.new)
235
+ config = namespace_class.new(data)
236
+
237
+ config.root_namespace = root_namespace || self
238
+
239
+ instance_variable_set(:"@#{namespace_name}", config)
240
+
241
+ block.call(config) if block_given?
242
+
243
+ config
244
+ end
245
+
246
+ def invalid_value_message(value, options)
247
+ array_tools = ::SleepingKingStudios::Tools::ArrayTools
248
+ valid_options =
249
+ array_tools
250
+ .humanize_list(
251
+ options[:enum].map(&:inspect),
252
+ last_separator: ' or '
253
+ )
254
+
255
+ "expected option to be #{valid_options}, but was #{value.inspect}"
256
+ end
257
+
258
+ def set_value(name, value, options)
259
+ writer_name = :"#{name}="
260
+
261
+ validate_value value, options
262
+
263
+ if data.respond_to?(writer_name)
264
+ data.send(writer_name, value)
265
+ else
266
+ # Store values locally if data source is immutable.
267
+ instance_variable_set(:"@#{name}", value)
268
+ end
269
+ end
270
+
271
+ def validate_value(value, options)
272
+ return if blank_value?(value) && options[:allow_nil]
273
+
274
+ return unless options[:enum] && !options[:enum].include?(value)
275
+
276
+ raise invalid_value_message(value, options)
277
+ end
278
+ end
279
+ end
280
+ # :nocov:
metadata CHANGED
@@ -1,49 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sleeping_king_studios-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob "Merlin" Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-06 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rake
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '12.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '12.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: thor
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.19'
34
17
  - - ">="
35
18
  - !ruby/object:Gem::Version
36
19
  version: 0.19.4
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
37
23
  type: :runtime
38
24
  prerelease: false
39
25
  version_requirements: !ruby/object:Gem::Requirement
40
26
  requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '0.19'
44
27
  - - ">="
45
28
  - !ruby/object:Gem::Version
46
29
  version: 0.19.4
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
47
33
  - !ruby/object:Gem::Dependency
48
34
  name: sleeping_king_studios-tools
49
35
  requirement: !ruby/object:Gem::Requirement
@@ -262,6 +248,7 @@ files:
262
248
  - lib/sleeping_king_studios/tasks/task.rb
263
249
  - lib/sleeping_king_studios/tasks/task_group.rb
264
250
  - lib/sleeping_king_studios/tasks/version.rb
251
+ - lib/sleeping_king_studios/tools/toolbox/configuration.rb
265
252
  homepage: http://sleepingkingstudios.com
266
253
  licenses:
267
254
  - MIT
@@ -281,7 +268,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
268
  - !ruby/object:Gem::Version
282
269
  version: '0'
283
270
  requirements: []
284
- rubygems_version: 3.0.3
271
+ rubygems_version: 3.1.2
285
272
  signing_key:
286
273
  specification_version: 4
287
274
  summary: A tasks toolkit for rapid development.