openhab-jrubyscripting 5.0.0.rc11 → 5.0.0.rc12

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/exec.rb +41 -41
  3. data/lib/openhab/core/items/date_time_item.rb +3 -2
  4. data/lib/openhab/core/items/generic_item.rb +90 -0
  5. data/lib/openhab/core/items/item.rb +9 -8
  6. data/lib/openhab/core/items/metadata/hash.rb +1 -1
  7. data/lib/openhab/core/items/metadata/namespace_hash.rb +10 -2
  8. data/lib/openhab/core/items/metadata/provider.rb +2 -2
  9. data/lib/openhab/core/items/persistence.rb +48 -4
  10. data/lib/openhab/core/items/registry.rb +10 -1
  11. data/lib/openhab/core/items/state_storage.rb +2 -2
  12. data/lib/openhab/core/proxy.rb +5 -0
  13. data/lib/openhab/core/registry.rb +12 -2
  14. data/lib/openhab/core/rules.rb +1 -1
  15. data/lib/openhab/core/things/links/provider.rb +38 -0
  16. data/lib/openhab/core/things/registry.rb +4 -0
  17. data/lib/openhab/core/timer.rb +3 -19
  18. data/lib/openhab/core/types/date_time_type.rb +1 -1
  19. data/lib/openhab/core.rb +3 -3
  20. data/lib/openhab/core_ext/java/duration.rb +2 -0
  21. data/lib/openhab/core_ext/java/local_date.rb +15 -7
  22. data/lib/openhab/core_ext/java/local_time.rb +13 -3
  23. data/lib/openhab/core_ext/java/month.rb +1 -1
  24. data/lib/openhab/core_ext/java/month_day.rb +13 -3
  25. data/lib/openhab/core_ext/java/period.rb +1 -1
  26. data/lib/openhab/core_ext/java/temporal_amount.rb +1 -1
  27. data/lib/openhab/core_ext/java/time.rb +5 -1
  28. data/lib/openhab/core_ext/java/zoned_date_time.rb +15 -2
  29. data/lib/openhab/core_ext/ruby/date.rb +2 -2
  30. data/lib/openhab/core_ext/ruby/numeric.rb +6 -1
  31. data/lib/openhab/dsl/items/builder.rb +25 -12
  32. data/lib/openhab/dsl/rules/automation_rule.rb +2 -23
  33. data/lib/openhab/dsl/rules/builder.rb +47 -2
  34. data/lib/openhab/dsl/version.rb +1 -1
  35. data/lib/openhab/dsl.rb +27 -11
  36. data/lib/openhab/rspec/helpers.rb +3 -2
  37. data/lib/openhab/rspec/hooks.rb +1 -0
  38. data/lib/openhab/rspec/mocks/timer.rb +33 -0
  39. data/lib/openhab/rspec.rb +9 -0
  40. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc3911eb787dc73ea31109aa6d4d8c3896a1019b381a70030f152c668f0b8f2e
4
- data.tar.gz: ebd2d7005e9f17827a4bf58d38b7fc2476a497cb428aab0270290c3c98461b80
3
+ metadata.gz: 38b109c413cbb8b06c2c43e57ad12e6278139b1cf56d887289ada297c8991272
4
+ data.tar.gz: 24e6235ce553d4e2ec9447c94407054b9c1c075c6a190a3ce5ed5ebb2421753c
5
5
  SHA512:
6
- metadata.gz: df4c1df793cd44700467728c63df6ba9d12ecf7111fc7daf2b9a8f4953c68575082f9f4b87f70a42bfedcc9af70d4537e45b6fb2d8b78ac8e7e3f7cca22aaf4b
7
- data.tar.gz: de1c8f5847bbbeb3eed3268ceedc2a61213b4f6ab269372a08bd4d8217f6b384a2c62b5ceb1f9de2777d264d0d6eb4e02fde6f245fa4fcc0dc03d068041a11bb
6
+ metadata.gz: a3e0f9f2f58d906ff72f5923817a2b5651a96f4710bbd29ad6ecffc3991722db5f8b1702de90e05ef1854ffe49c3d4214a699f271aaf0ac26a2dd03ad20c71f5
7
+ data.tar.gz: a51e80b23b82e7c38db1ac8d263b0a2776a70ad7fe9f401b1ae035f26a06d3660534e4c64c4d1c88a06fb9ee47ef64422b02bdfd26446e8edb148461c1403eca
@@ -4,47 +4,47 @@ module OpenHAB
4
4
  module Core
5
5
  module Actions
6
6
  # @see https://www.openhab.org/docs/configuration/actions.html#exec-actions Exec Actions
7
- class Exec
8
- class << self # rubocop:disable Lint/EmptyClass
9
- # @!method execute_command_line
10
- #
11
- # @return [void]
12
- #
13
- # @overload execute_command_line(command_line)
14
- #
15
- # Executes a command on the command line without waiting for the
16
- # command to complete.
17
- #
18
- # @param [String] command_line
19
- # @return [void]
20
- #
21
- # @example Execute an external command
22
- # rule 'Run a command' do
23
- # every :day
24
- # run do
25
- # Exec.execute_command_line('/bin/true')
26
- # end
27
- # end
28
- #
29
- # @overload execute_command_line(timeout, command_line)
30
- #
31
- # Executes a command on the command and waits timeout seconds for
32
- # the command to complete, returning the output from the command
33
- # as a String.
34
- #
35
- # @param [Duration] timeout
36
- # @param [String] command_line
37
- # @return [String]
38
- #
39
- # @example Execute an external command and process its results
40
- # rule 'Run a command' do
41
- # every :day
42
- # run do
43
- # TodaysHoliday_String.update(Exec.execute_command_line(5.seconds, '/home/cody/determine_holiday.rb')
44
- # end
45
- # end
46
- #
47
- end
7
+ class Exec # rubocop:disable Lint/EmptyClass
8
+ # @!scope class
9
+
10
+ # @!method execute_command_line
11
+ #
12
+ # @return [void]
13
+ #
14
+ # @overload execute_command_line(command_line)
15
+ #
16
+ # Executes a command on the command line without waiting for the
17
+ # command to complete.
18
+ #
19
+ # @param [String] command_line
20
+ # @return [void]
21
+ #
22
+ # @example Execute an external command
23
+ # rule 'Run a command' do
24
+ # every :day
25
+ # run do
26
+ # Exec.execute_command_line('/bin/true')
27
+ # end
28
+ # end
29
+ #
30
+ # @overload execute_command_line(timeout, command_line)
31
+ #
32
+ # Executes a command on the command and waits timeout seconds for
33
+ # the command to complete, returning the output from the command
34
+ # as a String.
35
+ #
36
+ # @param [Duration] timeout
37
+ # @param [String] command_line
38
+ # @return [String]
39
+ #
40
+ # @example Execute an external command and process its results
41
+ # rule 'Run a command' do
42
+ # every :day
43
+ # run do
44
+ # TodaysHoliday_String.update(Exec.execute_command_line(5.seconds, '/home/cody/determine_holiday.rb')
45
+ # end
46
+ # end
47
+ #
48
48
  end
49
49
  end
50
50
  end
@@ -45,9 +45,10 @@ module OpenHAB
45
45
  # Time types need formatted as ISO8601
46
46
  # @!visibility private
47
47
  def format_type(command)
48
- return Types::DateTimeType.new(command) if command.is_a?(java.time.ZonedDateTime)
48
+ return command if command.is_a?(Types::DateTimeType)
49
+ return Types::DateTimeType.new(command.to_zoned_date_time) if command.respond_to?(:to_zoned_date_time)
50
+ return Types::DateTimeType.new(DSL.try_parse_time_like(command.to_str)) if command.respond_to?(:to_str)
49
51
 
50
- command = command.iso8601 if command.respond_to?(:iso8601)
51
52
  super
52
53
  end
53
54
  end
@@ -163,9 +163,99 @@ module OpenHAB
163
163
  # make sure to use Type, because this method is used for both
164
164
  # #update and #command
165
165
  return type if type.is_a?(Types::Type)
166
+ return NULL if type.nil?
166
167
 
167
168
  type.to_s
168
169
  end
170
+
171
+ #
172
+ # Defers notifying openHAB of modifications to multiple attributes until the block is complete.
173
+ #
174
+ # @param [true, false] force When true, allow modifications to file-based items.
175
+ # Normally a FrozenError is raised when attempting to modify file-based items, since
176
+ # they will then be out-of-sync with the definition on disk. Advanced users may do this
177
+ # knowingly and intentionally though, so an escape hatch is provided to allow runtime
178
+ # modifications.
179
+ # @yield
180
+ # @return [Object] the block's return value
181
+ #
182
+ # @example Modify label and tags for an item
183
+ # MySwitch.modify do
184
+ # MySwitch.label = "New Label"
185
+ # MySwitch.tags = :labeled
186
+ # end
187
+ #
188
+ def modify(force: false)
189
+ raise ArgumentError, "you must pass a block to modify" unless block_given?
190
+ return yield if instance_variable_defined?(:@modifying) && @modifying
191
+
192
+ begin
193
+ provider = self.provider
194
+ if provider && !provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
195
+ raise FrozenError, "Cannot modify item #{name} from provider #{provider.inspect}." unless force
196
+
197
+ provider = nil
198
+ logger.debug("Forcing modifications to non-managed item #{name}")
199
+ end
200
+ @modified = false
201
+ @modifying = true
202
+
203
+ r = yield
204
+
205
+ provider&.update(self) if @modified
206
+ r
207
+ ensure
208
+ @modifying = false
209
+ end
210
+ end
211
+
212
+ # @!attribute [rw] label
213
+ # The item's descriptive label.
214
+ # @return [String]
215
+ def label=(value)
216
+ modify do
217
+ next if label == value
218
+
219
+ @modified = true
220
+ set_label(value)
221
+ end
222
+ end
223
+
224
+ # @!attribute [rw] category
225
+ # The item's category.
226
+ # @return [String]
227
+ def category=(value)
228
+ modify do
229
+ value = value&.to_s
230
+ next if category == value
231
+
232
+ @modified = true
233
+ set_category(value)
234
+ end
235
+ end
236
+
237
+ # @!attribute [rw] tags
238
+ # The item's tags
239
+ # @return [Array<String>]
240
+ # @overload tags
241
+ # Returns the item's tags.
242
+ # @return [Array<String>]
243
+ # @overload tags=(values)
244
+ # Sets the item's tags.
245
+ #
246
+ # To remove all tags, assign an empty array or nil.
247
+ # @param [Array<String,Symbol,Semantics::Tag>] values Tags to set.
248
+ # @return [void]
249
+ def tags=(values)
250
+ modify do
251
+ values = DSL::Items::ItemBuilder.normalize_tags(*values)
252
+ next if values.to_set == tags.to_set
253
+
254
+ @modified = true
255
+ remove_all_tags
256
+ add_tags(values)
257
+ end
258
+ end
169
259
  end
170
260
  end
171
261
  end
@@ -24,10 +24,6 @@ module OpenHAB
24
24
  # The item's name.
25
25
  # @return [String]
26
26
 
27
- # @!attribute [r] label
28
- # The item's descriptive label.
29
- # @return [String, nil]
30
-
31
27
  # @!attribute [r] accepted_command_types
32
28
  # @return [Array<Class>] An array of {Command}s that can be sent as commands to this item
33
29
 
@@ -35,7 +31,7 @@ module OpenHAB
35
31
  # @return [Array<Class>] An array of {State}s that can be sent as commands to this item
36
32
 
37
33
  #
38
- # The item's {#label} if one is defined, otherwise it's {#name}.
34
+ # The item's {GenericItem#label label} if one is defined, otherwise its {#name}.
39
35
  #
40
36
  # @return [String]
41
37
  #
@@ -46,7 +42,7 @@ module OpenHAB
46
42
  #
47
43
  # @!attribute [r] groups
48
44
  #
49
- # Return all groups that this item is part of
45
+ # Returns all groups that this item is part of
50
46
  #
51
47
  # @return [Array<Group>] All groups that this item is part of
52
48
  #
@@ -81,7 +77,7 @@ module OpenHAB
81
77
  # @example Access namespace1's configuration
82
78
  # Item1.metadata["namespace1"]["config1"]
83
79
  #
84
- # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn"t exist
80
+ # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn't exist
85
81
  # Item1.metadata.dig("namespace1", "config1") # => "foo"
86
82
  # Item1.metadata.dig("namespace2", "config1") # => nil
87
83
  #
@@ -189,7 +185,7 @@ module OpenHAB
189
185
  #
190
186
  # @return [Array<Thing>] An array of things or an empty array
191
187
  def things
192
- registry = OSGi.service("org.openhab.core.thing.link.ItemChannelLinkRegistry")
188
+ registry = Things::Links::Provider.registry
193
189
  channels = registry.get_bound_channels(name).to_a
194
190
  channels.map(&:thing_uid).uniq.map { |tuid| EntityLookup.lookup_thing(tuid) }.compact
195
191
  end
@@ -206,6 +202,11 @@ module OpenHAB
206
202
  "#{s}>"
207
203
  end
208
204
 
205
+ # @return [org.openhab.core.common.registry.Provider]
206
+ def provider
207
+ Provider.registry.provider_for(self)
208
+ end
209
+
209
210
  private
210
211
 
211
212
  # Allows sub-classes to append additional details to the type in an inspect string
@@ -384,7 +384,7 @@ module OpenHAB
384
384
  alias_method :to_s, :inspect
385
385
 
386
386
  #
387
- # @raise [RuntimeError] if the provider is not a
387
+ # @raise [FrozenError] if the provider is not a
388
388
  # {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that can be updated.
389
389
  # @return [org.openhab.core.common.registry.ManagedProvider]
390
390
  #
@@ -218,8 +218,12 @@ module OpenHAB
218
218
  return @hash.each_key(&block) unless attached?
219
219
  return to_enum(:each_key) unless block
220
220
 
221
- Provider.registry.all.each do |meta|
222
- yield meta.uid.namespace if meta.uid.item_name == @item_name
221
+ if Provider.registry.respond_to?(:get_all_namespaces)
222
+ keys.each(&block)
223
+ else
224
+ Provider.registry.all.each do |meta|
225
+ yield meta.uid.namespace if meta.uid.item_name == @item_name
226
+ end
223
227
  end
224
228
  self
225
229
  end
@@ -313,6 +317,10 @@ module OpenHAB
313
317
 
314
318
  # @!visibility private
315
319
  def keys
320
+ if Provider.registry.respond_to?(:get_all_namespaces)
321
+ return Provider.registry.get_all_namespaces(@item_name).to_a
322
+ end
323
+
316
324
  each_key.to_a
317
325
  end
318
326
 
@@ -32,8 +32,8 @@ module OpenHAB
32
32
  # @return [void]
33
33
  #
34
34
  def remove_item_metadata(item_name)
35
- @elements.delete_if do |k, v|
36
- next unless k.item_name == item_name
35
+ @elements.delete_if do |_k, v|
36
+ next unless v.uid.item_name == item_name
37
37
 
38
38
  notify_listeners_about_removed_element(v)
39
39
  true
@@ -77,7 +77,6 @@ module OpenHAB
77
77
  %i[changed_since?
78
78
  count_since
79
79
  count_state_changes_since
80
- evolution_rate
81
80
  historic_state
82
81
  maximum_since
83
82
  minimum_since
@@ -183,11 +182,22 @@ module OpenHAB
183
182
  # @return [true,false] True if the item's state changed between `start` and `finish`, False otherwise.
184
183
 
185
184
  # @!method evolution_rate(timestamp, service = nil)
186
- # Returns the evolution rate of the item's state since the given time
187
- # @param [#to_zoned_date_time] timestamp The point in time from which to search
188
- # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
185
+ # Returns the evolution rate of the item's state
189
186
  # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
190
187
  # or nil if no previous state could be found.
188
+ # @overload evolution_rate(timestamp, service = nil)
189
+ # Returns the evolution rate of the item's state since the given time
190
+ # @param [#to_zoned_date_time] timestamp The point in time from which to search
191
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
192
+ # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
193
+ # or nil if no previous state could be found.
194
+ # @overload evolution_rate(start, finish, service = nil)
195
+ # Returns the evolution rate of the item's state between two points in time
196
+ # @param [#to_zoned_date_time] start The point in time from which to search
197
+ # @param [#to_zoned_date_time] finish The point in time to which to search
198
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
199
+ # @return [DecimalType, QuantityType, nil] The evolution rate between `start` and `finish`,
200
+ # or nil if no previous state could be found.
191
201
 
192
202
  # @!method historic_state(timestamp, service = nil)
193
203
  # Returns the the item's state at the given time
@@ -317,6 +327,40 @@ module OpenHAB
317
327
  end
318
328
  end
319
329
 
330
+ # evolution_rate's "between" method is overloaded with the same name
331
+ method = :evolution_rate
332
+ define_method(method) do |start, finish_or_service = nil, service = nil|
333
+ if service.nil?
334
+ if finish_or_service.respond_to?(:to_zoned_date_time)
335
+ service = persistence_service
336
+ finish = finish_or_service
337
+ else
338
+ service = finish_or_service || persistence_service
339
+ finish = nil
340
+ end
341
+ else
342
+ finish = finish_or_service
343
+ end
344
+
345
+ result = if finish
346
+ Actions::PersistenceExtensions.public_send(
347
+ method,
348
+ self,
349
+ start.to_zoned_date_time,
350
+ finish.to_zoned_date_time,
351
+ service&.to_s
352
+ )
353
+ else
354
+ Actions::PersistenceExtensions.public_send(
355
+ method,
356
+ self,
357
+ start.to_zoned_date_time,
358
+ service&.to_s
359
+ )
360
+ end
361
+ wrap_result(result, method)
362
+ end
363
+
320
364
  alias_method :state_changes_since, :count_state_changes_since
321
365
  alias_method :state_changes_between, :count_state_changes_between
322
366
 
@@ -59,16 +59,25 @@ module OpenHAB
59
59
  #
60
60
  # The item must be a managed item (typically created by Ruby or in the UI).
61
61
  #
62
+ # Any associated metadata or channel links are also removed.
63
+ #
62
64
  # @param [String, Item] item_name
63
65
  # @param recursive [true, false] Remove the item's members if it's a group
64
66
  # @return [Item, nil] The removed item, if found.
65
67
  def remove(item_name, recursive: false)
66
68
  item_name = item_name.name if item_name.is_a?(Item)
67
69
  provider = Provider.registry.provider_for(item_name)
68
- unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
70
+ unless provider.is_a?(ManagedProvider)
69
71
  raise "Cannot remove item #{item_name} from non-managed provider #{provider.inspect}"
70
72
  end
71
73
 
74
+ Metadata::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
75
+ managed_provider.remove_item_metadata(item_name)
76
+ end
77
+
78
+ Things::Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
79
+ managed_provider.remove_links_for_item(item_name)
80
+ end
72
81
  provider.remove(item_name, recursive)
73
82
  end
74
83
  end
@@ -12,13 +12,13 @@ module OpenHAB
12
12
  #
13
13
  # Create a StateStorage object that stores the states of the given items
14
14
  #
15
- # @param [Array<Item>] items A list of items
15
+ # @param [Item] items A list of items
16
16
  #
17
17
  # @return [StateStorage] A state storage object
18
18
  #
19
19
  # @!visibility private
20
20
  def self.from_items(*items)
21
- StateStorage.new($events.store_states(*items).to_h)
21
+ StateStorage.new($events.store_states(*items.map(&:to_java)).to_h)
22
22
  end
23
23
 
24
24
  #
@@ -120,6 +120,11 @@ module OpenHAB
120
120
  # define a sub-class of EventSubscriber as a child class of the including class
121
121
  klass.const_set(:EventSubscriber, Class.new(EventSubscriber))
122
122
  end
123
+
124
+ # @!visibility private
125
+ def to_java
126
+ __getobj__
127
+ end
123
128
  end
124
129
  end
125
130
  end
@@ -4,7 +4,7 @@ module OpenHAB
4
4
  module Core
5
5
  Registry = org.openhab.core.common.registry.AbstractRegistry
6
6
 
7
- Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement
7
+ Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement, :providerToElements
8
8
 
9
9
  # @abstract
10
10
  #
@@ -19,12 +19,22 @@ module OpenHAB
19
19
  #
20
20
  def provider_for(key)
21
21
  elementReadLock.lock
22
- return nil unless (element = identifierToElement[key])
22
+ if key.is_a?(org.openhab.core.common.registry.Identifiable)
23
+ element = key
24
+ else
25
+ return nil unless (element = identifierToElement[key])
26
+ end
23
27
 
24
28
  elementToProvider[element]
25
29
  ensure
26
30
  elementReadLock.unlock
27
31
  end
32
+
33
+ # @!attribute [r] providers
34
+ # @return [Enumerable<org.openhab.core.common.registry.Provider>]
35
+ def providers
36
+ providerToElements.keys
37
+ end
28
38
  end
29
39
  end
30
40
  end
@@ -13,7 +13,7 @@ module OpenHAB
13
13
 
14
14
  class << self
15
15
  #
16
- # @!attribute [r] rule_manager
16
+ # @!attribute [r] manager
17
17
  # @return [org.openhab.core.automation.RuleManager] The openHAB rule manager/engine
18
18
  #
19
19
  def manager
@@ -33,6 +33,44 @@ module OpenHAB
33
33
  current.add(link)
34
34
  end
35
35
  end
36
+
37
+ #
38
+ # Removes all links to a given item.
39
+ #
40
+ # @param [String] item_name
41
+ # @return [Integer] how many links were removed
42
+ #
43
+ def remove_links_for_item(item_name)
44
+ count = 0
45
+ @elements.delete_if do |_k, v|
46
+ next unless v.item_name == item_name
47
+
48
+ count += 1
49
+ notify_listeners_about_removed_element(v)
50
+ true
51
+ end
52
+ count
53
+ end
54
+ alias_method :removeLinksForItem, :remove_links_for_item
55
+
56
+ #
57
+ # Removes all links to a given thing.
58
+ #
59
+ # @param [ThingUID] thing_uid
60
+ # @return [Integer] how many links were removed
61
+ #
62
+ def remove_links_for_thing(thing_uid)
63
+ count = 0
64
+ @elements.delete_if do |_k, v|
65
+ next unless v.linked_uid.thing_uid == thing_uid
66
+
67
+ count += 1
68
+ notify_listeners_about_removed_element(v)
69
+ true
70
+ end
71
+ count
72
+ end
73
+ alias_method :removeLinksForThing, :remove_links_for_thing
36
74
  end
37
75
  end
38
76
  end
@@ -61,6 +61,10 @@ module OpenHAB
61
61
  raise "Cannot remove thing #{thing_uid} from non-managed provider #{provider.inspect}"
62
62
  end
63
63
 
64
+ Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
65
+ managed_provider.remove_links_for_thing(thing_uid)
66
+ end
67
+
64
68
  provider.remove(thing_uid)
65
69
  end
66
70
  end
@@ -28,7 +28,7 @@ module OpenHAB
28
28
  # @return [true,false]
29
29
 
30
30
  def_delegator :@timer, :has_terminated, :terminated?
31
- def_delegators :@timer, :active?, :cancelled?, :running?
31
+ def_delegators :@timer, :active?, :cancelled?, :running?, :execution_time
32
32
 
33
33
  # @return [Object, nil]
34
34
  attr_accessor :id
@@ -49,19 +49,7 @@ module OpenHAB
49
49
  @id = id
50
50
  @thread_locals = thread_locals
51
51
  @block = block
52
- @timer = if defined?(ScriptExecution)
53
- ScriptExecution.create_timer(1.minute.from_now) { execute }
54
- else # DEPRECATED: openHAB 3.4.0
55
- org.openhab.core.model.script.actions.ScriptExecution.create_timer(
56
- # create it far enough in the future so it won't execute until we finish setting it up
57
- 1.minute.from_now,
58
- # when running in rspec, it may have troubles finding this class
59
- # for auto-conversion of block to interface, so use .impl
60
- org.eclipse.xtext.xbase.lib.Procedures::Procedure0.impl { execute }
61
- )
62
- end
63
- # DEPRECATED: openHAB 3.4.0.M6
64
- @timer.class.field_reader :future unless @timer.respond_to?(:future)
52
+ @timer = ScriptExecution.create_timer(1.minute.from_now) { execute }
65
53
  reschedule(@time)
66
54
  end
67
55
 
@@ -79,11 +67,7 @@ module OpenHAB
79
67
  alias_method :to_s, :inspect
80
68
 
81
69
  # @!attribute [r] execution_time
82
- # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
83
- def execution_time
84
- # DEPRECATED: openHAB 3.4.0.M6 (just remove the entire method)
85
- @timer.future.scheduled_time
86
- end
70
+ # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
87
71
 
88
72
  #
89
73
  # Reschedule timer
@@ -46,7 +46,7 @@ module OpenHAB
46
46
  rescue java.lang.StringIndexOutOfBoundsException, java.lang.IllegalArgumentException => e
47
47
  # Try Ruby's Time.parse if DateTimeType parser fails
48
48
  begin
49
- ::Time.parse(time_string).to_zoned_date_time
49
+ DateTimeType.new(::Time.parse(time_string).to_zoned_date_time)
50
50
  rescue ArgumentError
51
51
  raise ArgumentError, e.message
52
52
  end
data/lib/openhab/core.rb CHANGED
@@ -3,12 +3,12 @@
3
3
  module OpenHAB
4
4
  # Contains classes and modules that wrap actual openHAB objects
5
5
  module Core
6
- # The openHAB Version. >= 3.3.0 is required.
6
+ # The openHAB Version. >= 3.4.0 is required.
7
7
  # @return [String]
8
8
  VERSION = org.openhab.core.OpenHAB.version.freeze
9
9
 
10
- unless Gem::Version.new(VERSION) >= Gem::Version.new("3.3.0")
11
- raise "`openhab-jrubyscripting` requires openHAB >= 3.3.0"
10
+ unless Gem::Version.new(VERSION) >= Gem::Version.new("3.4.0")
11
+ raise "`openhab-jrubyscripting` requires openHAB >= 3.4.0"
12
12
  end
13
13
 
14
14
  # @return [Integer] Number of seconds to wait between checks for automation manager
@@ -52,6 +52,8 @@ module OpenHAB
52
52
  return to_f <=> other if other.is_a?(Numeric)
53
53
 
54
54
  super
55
+ rescue TypeError
56
+ nil
55
57
  end
56
58
 
57
59
  #
@@ -7,16 +7,24 @@ module OpenHAB
7
7
  module Java
8
8
  java_import java.time.LocalDate
9
9
 
10
- # Extensions to LocalDate
10
+ # Extensions to {java.time.LocalDate}
11
11
  class LocalDate
12
12
  include Time
13
13
  include Between
14
14
  include Ephemeris
15
15
 
16
- class << self # rubocop:disable Lint/EmptyClass
17
- # @!attribute [r] now
18
- # @return [ZonedDateTime]
19
- end
16
+ # @!scope class
17
+
18
+ # @!attribute [r] now
19
+ # @return [LocalDate]
20
+
21
+ # @!method parse(text, formatter=nil)
22
+ # Converts the given text into a LocalDate.
23
+ # @param [String] text The text to parse
24
+ # @param [java.time.format.DateTimeFormatter] formatter The formatter to use
25
+ # @return [LocalDate]
26
+
27
+ # @!scope instance
20
28
 
21
29
  # @param [TemporalAmount, LocalDate, Numeric] other
22
30
  # If other is a Numeric, it's interpreted as days.
@@ -25,11 +33,11 @@ module OpenHAB
25
33
  def -(other)
26
34
  case other
27
35
  when Date
28
- Period.of_days(day_of_year - other.yday)
36
+ self - other.to_local_date
29
37
  when MonthDay
30
38
  self - other.at_year(year)
31
39
  when LocalDate
32
- Period.of_days(day_of_year - other.day_of_year)
40
+ Period.between(other, self)
33
41
  when Duration
34
42
  minus_days(other.to_days)
35
43
  when Numeric
@@ -7,6 +7,8 @@ module OpenHAB
7
7
  module Java
8
8
  java_import java.time.LocalTime
9
9
 
10
+ #
11
+ # Extensions to {java.time.LocalTime}
10
12
  #
11
13
  # @example
12
14
  # break_time = LocalTime::NOON
@@ -36,15 +38,23 @@ module OpenHAB
36
38
  include Between
37
39
  # @!parse include Time
38
40
 
39
- # @!visibility private
40
41
  class << self
42
+ # @!attribute [r] now
43
+ # @return [LocalTime]
44
+
45
+ # @!visibility private
46
+ alias_method :raw_parse, :parse
47
+
41
48
  #
42
- # Parses strings in the form "h[:mm[:ss]] [am/pm]"
49
+ # Parses strings in the form "h[:mm[:ss]] [am/pm]" when no formatter is given.
43
50
  #
44
51
  # @param [String] string
52
+ # @param [java.time.format.DateTimeFormatter] formatter The formatter to use
45
53
  # @return [LocalTime]
46
54
  #
47
- def parse(string)
55
+ def parse(string, formatter = nil)
56
+ return raw_parse(string, formatter) if formatter
57
+
48
58
  format = /(am|pm)$/i.match?(string) ? "h[:mm[:ss][.S]][ ]a" : "H[:mm[:ss][.S]]"
49
59
  java_send(:parse, [java.lang.CharSequence, java.time.format.DateTimeFormatter],
50
60
  string, java.time.format.DateTimeFormatterBuilder.new
@@ -7,7 +7,7 @@ module OpenHAB
7
7
  module Java
8
8
  Month = java.time.Month
9
9
 
10
- # Extensions to Month
10
+ # Extensions to {java.time.Month}
11
11
  class Month
12
12
  include Between
13
13
  # @!parse include Time
@@ -7,7 +7,7 @@ module OpenHAB
7
7
  module Java
8
8
  java_import java.time.MonthDay
9
9
 
10
- # Extensions to MonthDay
10
+ # Extensions to {java.time.MonthDay}
11
11
  class MonthDay
12
12
  include Between
13
13
  include Ephemeris
@@ -39,12 +39,22 @@ module OpenHAB
39
39
 
40
40
  # @return [MonthDay]
41
41
  def +(other)
42
- (LocalDate.of(1900, month, day_of_month) + other).to_month_day
42
+ case other
43
+ when java.time.temporal.TemporalAmount, Numeric
44
+ (LocalDate.of(1900, month, day_of_month) + other).to_month_day
45
+ else
46
+ (to_local_date(other.to_local_date) + other).to_month_day
47
+ end
43
48
  end
44
49
 
45
50
  # @return [MonthDay, Period]
46
51
  def -(other)
47
- d = (LocalDate.of(1900, month, day_of_month) - other)
52
+ d = case other
53
+ when java.time.temporal.TemporalAmount, Numeric
54
+ LocalDate.of(1900, month, day_of_month) - other
55
+ else
56
+ to_local_date(other.to_local_date) - other
57
+ end
48
58
  return d if d.is_a?(java.time.Period)
49
59
 
50
60
  d.to_month_day
@@ -5,7 +5,7 @@ module OpenHAB
5
5
  module Java
6
6
  java_import java.time.Period
7
7
 
8
- # Extensions to Period
8
+ # Extensions to {java.time.Period}
9
9
  class Period
10
10
  # @!parse include TemporalAmount
11
11
 
@@ -5,7 +5,7 @@ module OpenHAB
5
5
  module Java
6
6
  java_import java.time.temporal.TemporalAmount
7
7
 
8
- # Extensions to TemporalAmount
8
+ # Extensions to {java.time.temporal.TemporalAmount}
9
9
  module TemporalAmount
10
10
  # Subtract `self` to {ZonedDateTime.now}
11
11
  # @return [ZonedDateTime]
@@ -50,7 +50,11 @@ module OpenHAB
50
50
  # Convert `other` to this class, if possible
51
51
  # @return [Array, nil]
52
52
  def coerce(other)
53
- [other.send(self.class.coercion_method), self] if other.respond_to?(self.class.coercion_method)
53
+ coercion_method = self.class.coercion_method
54
+ return unless other.respond_to?(coercion_method)
55
+ return [other.send(coercion_method), self] if other.method(coercion_method).arity.zero?
56
+
57
+ [other.send(coercion_method, self), self]
54
58
  end
55
59
  end
56
60
  end
@@ -7,18 +7,31 @@ module OpenHAB
7
7
  module Java
8
8
  ZonedDateTime = java.time.ZonedDateTime
9
9
 
10
- # Extensions to ZonedDateTime
10
+ # Extensions to {java.time.ZonedDateTime}
11
11
  class ZonedDateTime
12
12
  include Time
13
13
  include Between
14
14
 
15
15
  class << self # rubocop:disable Lint/EmptyClass
16
+ # @!scope class
17
+
16
18
  # @!attribute [r] now
17
19
  # @return [ZonedDateTime]
20
+
21
+ # @!method parse(text, formatter = nil)
22
+ # Parses a string into a ZonedDateTime object.
23
+ #
24
+ # @param [String] text The text to parse.
25
+ # @param [java.time.format.DateTimeFormatter] formatter The formatter to use.
26
+ # @return [ZonedDateTime]
18
27
  end
19
28
 
29
+ # @!scope instance
30
+
20
31
  # @return [LocalTime]
21
- alias_method :to_local_time, :toLocalTime
32
+ def to_local_time(_context = nil)
33
+ toLocalTime
34
+ end
22
35
 
23
36
  # @return [Month]
24
37
  alias_method :to_month, :month
@@ -85,9 +85,9 @@ class Date
85
85
  #
86
86
  def coerce(other)
87
87
  return nil unless other.respond_to?(:to_date)
88
- return [other.to_date(self), self] if other.method(:to_date).arity == 1
88
+ return [other.to_date, self] if other.method(:to_date).arity.zero?
89
89
 
90
- [other.to_date, self]
90
+ [other.to_date(self), self]
91
91
  end
92
92
 
93
93
  remove_method :inspect
@@ -151,7 +151,12 @@ module OpenHAB
151
151
  # @return [QuantityType] `self` as a {QuantityType} of the supplied Unit
152
152
  #
153
153
  def |(unit) # rubocop:disable Naming/BinaryOperatorParameterName
154
- unit = org.openhab.core.types.util.UnitUtils.parse_unit(unit.to_str) if unit.respond_to?(:to_str)
154
+ if unit.respond_to?(:to_str)
155
+ parsed_unit = org.openhab.core.types.util.UnitUtils.parse_unit(unit.to_str)
156
+ raise ArgumentError, "Unknown unit #{unit}" unless parsed_unit
157
+
158
+ unit = parsed_unit
159
+ end
155
160
 
156
161
  return super unless unit.is_a?(javax.measure.Unit)
157
162
 
@@ -187,6 +187,30 @@ module OpenHAB
187
187
  def item_factory
188
188
  @item_factory ||= org.openhab.core.library.CoreItemFactory.new
189
189
  end
190
+
191
+ #
192
+ # Convert the given array to an array of strings.
193
+ # Convert Semantics classes to their simple name.
194
+ #
195
+ # @param [String,Symbol,Semantics::Tag] tags A list of strings, symbols, or Semantics classes
196
+ # @return [Array] An array of strings
197
+ #
198
+ # @example
199
+ # tags = normalize_tags("tag1", Semantics::LivingRoom)
200
+ #
201
+ # @!visibility private
202
+ def normalize_tags(*tags)
203
+ semantics = proc { |tag| tag.respond_to?(:java_class) && tag < Semantics::Tag }
204
+
205
+ tags.compact.map do |tag|
206
+ case tag
207
+ when String then tag
208
+ when Symbol then tag.to_s
209
+ when semantics then tag.java_class.simple_name
210
+ else raise ArgumentError, "`#{tag}` must be a subclass of Semantics::Tag, a `Symbol`, or a `String`."
211
+ end
212
+ end
213
+ end
190
214
  end
191
215
 
192
216
  # @param dimension [Symbol, nil] The unit dimension for a {NumberItem} (see {ItemBuilder#dimension})
@@ -294,18 +318,7 @@ module OpenHAB
294
318
  # @return [void]
295
319
  #
296
320
  def tag(*tags)
297
- unless tags.all? do |tag|
298
- tag.is_a?(String) ||
299
- tag.is_a?(Symbol) ||
300
- (tag.is_a?(Module) && tag < Semantics::Tag)
301
- end
302
- raise ArgumentError, "`tag` must be a subclass of Semantics::Tag, or a `String``."
303
- end
304
-
305
- tags.each do |tag|
306
- tag = tag.name.split("::").last if tag.is_a?(Module) && tag < Semantics::Tag
307
- @tags << tag.to_s
308
- end
321
+ @tags += self.class.normalize_tags(*tags)
309
322
  end
310
323
 
311
324
  #
@@ -35,7 +35,8 @@ module OpenHAB
35
35
  super()
36
36
  set_name(config.name)
37
37
  set_description(config.description)
38
- set_tags(to_string_set(config.tags))
38
+ tags = DSL::Items::ItemBuilder.normalize_tags(*config.tags)
39
+ set_tags(tags.to_set)
39
40
  set_triggers(config.triggers)
40
41
  self.uid = config.uid
41
42
  @run_context = config.caller
@@ -297,28 +298,6 @@ module OpenHAB
297
298
  @run_context.instance_exec(&task.block)
298
299
  end
299
300
 
300
- #
301
- # Convert the given array to a set of strings.
302
- # Convert Semantics classes to their simple name
303
- #
304
- # @example
305
- # to_string_set("tag1", Semantics::LivingRoom)
306
- #
307
- # @param tags [Array] An array of strings or Semantics classes
308
- #
309
- # @return [Set] A set of strings
310
- #
311
- def to_string_set(*tags)
312
- tags = tags.flatten.map do |tag|
313
- if tag.respond_to?(:java_class) && tag < org.openhab.core.semantics.Tag
314
- tag.java_class.simple_name
315
- else
316
- tag.to_s
317
- end
318
- end
319
- Set.new(tags)
320
- end
321
-
322
301
  #
323
302
  # Create a new hash in which all elements are converted to strings
324
303
  #
@@ -358,7 +358,7 @@ module OpenHAB
358
358
  #
359
359
  # Set the rule's tags.
360
360
  #
361
- # @param [String, Class, Array<String, Class>] tags
361
+ # @param [String, Symbol, Semantics::Tag] tags A list of tags to assign to the rule.
362
362
  # @return [void]
363
363
  #
364
364
  # @example
@@ -1101,7 +1101,10 @@ module OpenHAB
1101
1101
  # :saturday,
1102
1102
  # :sunday] value
1103
1103
  # When to execute rule.
1104
- # @param [LocalTime, String, nil] at What time of day to execute rule
1104
+ # @param [LocalTime, String, Core::Items::DateTimeItem, nil] at What time of day to execute rule
1105
+ # If `value` is `:day`, `at` can be a {Core::Items::DateTimeItem DateTimeItem}, and
1106
+ # the trigger will run every day at the (time only portion of) current state of the
1107
+ # item. If the item is {NULL} or {UNDEF}, the trigger will not run.
1105
1108
  # @param [Object] attach Object to be attached to the trigger
1106
1109
  # @return [void]
1107
1110
  #
@@ -1157,11 +1160,23 @@ module OpenHAB
1157
1160
  # run { logger.info "Happy Valentine's Day!" }
1158
1161
  # end
1159
1162
  #
1163
+ # @example
1164
+ # rule "Every day at sunset" do
1165
+ # every :day, at: Sunset_Time
1166
+ # run { logger.info "It's getting dark" }
1167
+ # end
1168
+ #
1160
1169
  def every(value, at: nil, attach: nil)
1161
1170
  return every(java.time.MonthDay.parse(value), at: at, attach: attach) if value.is_a?(String)
1162
1171
 
1163
1172
  @ruby_triggers << [:every, value, { at: at }]
1164
1173
 
1174
+ if value == :day && at.is_a?(Item)
1175
+ raise ArgumentError, "Attachments are not supported with dynamic datetime triggers" unless attach.nil?
1176
+
1177
+ return trigger("timer.DateTimeTrigger", itemName: at.name, timeOnly: true)
1178
+ end
1179
+
1165
1180
  cron_expression = case value
1166
1181
  when Symbol then Cron.from_symbol(value, at)
1167
1182
  when Duration then Cron.from_duration(value, at)
@@ -1502,6 +1517,36 @@ module OpenHAB
1502
1517
  trigger("core.GenericEventTrigger", eventTopic: topic, eventSource: source, eventTypes: types, attach: attach)
1503
1518
  end
1504
1519
 
1520
+ #
1521
+ # Creates a trigger based on the time stored in a {DateTimeItem}
1522
+ #
1523
+ # The trigger will dynamically update any time the state of the item
1524
+ # changes. If the item is {NULL} or {UNDEF}, the trigger will not run.
1525
+ #
1526
+ # @param [Item, String, Symbol] item The item (or it's name)
1527
+ # @return [void]
1528
+ #
1529
+ # @example
1530
+ # rule "say hello when the kids get home from school" do
1531
+ # at HomeFromSchool_Time
1532
+ # run do
1533
+ # KitchenEcho_TTS << "hi kids! how was school?"
1534
+ # end
1535
+ # end
1536
+ #
1537
+ # rule "set home from school time" do
1538
+ # on_load
1539
+ # every :day, at: "5:00am" do
1540
+ # run do
1541
+ # HomeFromSchool_Time.ensure.update(school_day? ? LocalTime.parse("3:30pm") : NULL)
1542
+ # end
1543
+ # end
1544
+ #
1545
+ def at(item)
1546
+ item = item.name if item.is_a?(Item)
1547
+ trigger("timer.DateTimeTrigger", itemName: item.to_s)
1548
+ end
1549
+
1505
1550
  #
1506
1551
  # Create a generic trigger given the trigger type uid and a configuration hash
1507
1552
  #
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.0.0.rc11"
7
+ VERSION = "5.0.0.rc12"
8
8
  end
9
9
  end
data/lib/openhab/dsl.rb CHANGED
@@ -152,8 +152,6 @@ module OpenHAB
152
152
  #
153
153
  # @see Core::ValueCache ValueCache
154
154
  #
155
- # @since openHAB 3.4.0
156
- #
157
155
  def shared_cache
158
156
  $sharedCache
159
157
  end
@@ -523,9 +521,6 @@ module OpenHAB
523
521
  # end # the states will be restored here
524
522
  #
525
523
  def store_states(*items)
526
- items = items.flatten.map do |item|
527
- item.respond_to?(:__getobj__) ? item.__getobj__ : item
528
- end
529
524
  states = Core::Items::StateStorage.from_items(*items)
530
525
  if block_given?
531
526
  yield
@@ -604,18 +599,39 @@ module OpenHAB
604
599
  # Item1.average_since(12.hours)
605
600
  # end
606
601
  #
607
- # @see OpenHAB::Core::Items::Persistence
608
- #
609
- # @param [Object] service service either as a String or a Symbol
602
+ # @param [Object] service Persistence service either as a String or a Symbol
610
603
  # @yield [] Block executed in context of the supplied persistence service
611
604
  # @return [Object] The return value from the block.
612
605
  #
606
+ # @see persistence!
607
+ # @see OpenHAB::Core::Items::Persistence
608
+ #
613
609
  def persistence(service)
614
- old = Thread.current[:openhab_persistence_service]
615
- Thread.current[:openhab_persistence_service] = service
610
+ old = persistence!(service)
616
611
  yield
617
612
  ensure
618
- Thread.current[:openhab_persistence_service] = old
613
+ persistence!(old)
614
+ end
615
+
616
+ #
617
+ # Permanently sets the default persistence service for the current thread
618
+ #
619
+ # @note This method is only intended for use at the top level of rule
620
+ # scripts. If it's used within library methods, or hap-hazardly within
621
+ # rules, things can get very confusing because the prior state won't be
622
+ # properly restored.
623
+ #
624
+ # @param [Object] service Persistence service either as a String or a Symbol. When nil, use
625
+ # the system's default persistence service.
626
+ # @return [Object,nil] The previous persistence service settings, or nil when using the system's default.
627
+ #
628
+ # @see persistence
629
+ # @see OpenHAB::Core::Items::Persistence
630
+ #
631
+ def persistence!(service = nil)
632
+ old = Thread.current[:openhab_persistence_service]
633
+ Thread.current[:openhab_persistence_service] = service
634
+ old
619
635
  end
620
636
 
621
637
  #
@@ -265,12 +265,13 @@ module OpenHAB
265
265
  # @return [void]
266
266
  #
267
267
  def load_rules
268
- automation_path = "#{org.openhab.core.OpenHAB.config_folder}/automation/ruby"
268
+ automation_paths = Array(::RSpec.configuration.openhab_automation_search_paths)
269
+
269
270
  lib_dirs = rubylib_dirs.map { |d| File.join(d, "") }
270
271
  lib_dirs << File.join(gem_home, "")
271
272
 
272
273
  SuspendRules.suspend_rules do
273
- files = Dir["#{automation_path}/**/*.rb"]
274
+ files = automation_paths.map { |p| Dir["#{p}/**/*.rb"] }.flatten
274
275
  files.reject! do |f|
275
276
  lib_dirs.any? { |l| f.start_with?(l) }
276
277
  end
@@ -100,6 +100,7 @@ module OpenHAB
100
100
  restore_autoupdate_items
101
101
  Mocks::PersistenceService.instance.reset
102
102
  Hooks.cache_script_extension.sharedCache.clear if DSL.shared_cache
103
+ DSL.persistence!(nil)
103
104
  end
104
105
  end
105
106
  end
@@ -17,6 +17,39 @@ module OpenHAB
17
17
  end
18
18
  ZonedDateTime.singleton_class.prepend(MockedZonedDateTime)
19
19
 
20
+ # @!visibility private
21
+ module MockedLocalDate
22
+ def now
23
+ mocked_time_stack_item = Timecop.top_stack_item
24
+ return super unless mocked_time_stack_item
25
+
26
+ mocked_time_stack_item.time.to_zoned_date_time.to_local_date
27
+ end
28
+ end
29
+ LocalDate.singleton_class.prepend(MockedLocalDate)
30
+
31
+ # @!visibility private
32
+ module MockedLocalTime
33
+ def now
34
+ mocked_time_stack_item = Timecop.top_stack_item
35
+ return super unless mocked_time_stack_item
36
+
37
+ mocked_time_stack_item.time.to_zoned_date_time.to_local_time
38
+ end
39
+ end
40
+ LocalTime.singleton_class.prepend(MockedLocalTime)
41
+
42
+ # @!visibility private
43
+ module MockedMonthDay
44
+ def now
45
+ mocked_time_stack_item = Timecop.top_stack_item
46
+ return super unless mocked_time_stack_item
47
+
48
+ mocked_time_stack_item.time.to_zoned_date_time.to_month_day
49
+ end
50
+ end
51
+ MonthDay.singleton_class.prepend(MockedMonthDay)
52
+
20
53
  # extend Timecop to support Java time classes
21
54
  # @!visibility private
22
55
  module TimeCopStackItem
data/lib/openhab/rspec.rb CHANGED
@@ -15,3 +15,12 @@ require_relative "rspec/configuration"
15
15
  require_relative "rspec/helpers"
16
16
  require_relative "rspec/karaf"
17
17
  require_relative "rspec/hooks"
18
+
19
+ return unless defined?(RSpec)
20
+
21
+ RSpec.configure do |c|
22
+ c.add_setting :openhab_automation_search_paths, default: [
23
+ "#{org.openhab.core.OpenHAB.config_folder}/automation/ruby",
24
+ "#{org.openhab.core.OpenHAB.config_folder}/automation/jsr223"
25
+ ]
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-jrubyscripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.rc11
4
+ version: 5.0.0.rc12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-25 00:00:00.000000000 Z
11
+ date: 2023-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler