vigilem-core 0.0.9

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/lib/vigilem/core.rb +9 -0
  3. data/lib/vigilem/core/abstract_device.rb +97 -0
  4. data/lib/vigilem/core/adapters.rb +2 -0
  5. data/lib/vigilem/core/adapters/adapter.rb +57 -0
  6. data/lib/vigilem/core/adapters/basic_adapter.rb +43 -0
  7. data/lib/vigilem/core/adapters/buffered_adapter.rb +28 -0
  8. data/lib/vigilem/core/buffer.rb +151 -0
  9. data/lib/vigilem/core/buffer_handler.rb +95 -0
  10. data/lib/vigilem/core/default_buffer.rb +45 -0
  11. data/lib/vigilem/core/demultiplexer.rb +225 -0
  12. data/lib/vigilem/core/device.rb +43 -0
  13. data/lib/vigilem/core/event_handler.rb +156 -0
  14. data/lib/vigilem/core/eventable.rb +80 -0
  15. data/lib/vigilem/core/hooks.rb +36 -0
  16. data/lib/vigilem/core/hooks/callback.rb +66 -0
  17. data/lib/vigilem/core/hooks/callback_proc.rb +25 -0
  18. data/lib/vigilem/core/hooks/conditional_hook.rb +62 -0
  19. data/lib/vigilem/core/hooks/hook.rb +193 -0
  20. data/lib/vigilem/core/hooks/inheritable.rb +24 -0
  21. data/lib/vigilem/core/hooks/meta_callback.rb +53 -0
  22. data/lib/vigilem/core/hooks/utils.rb +23 -0
  23. data/lib/vigilem/core/hub.rb +50 -0
  24. data/lib/vigilem/core/input_system_handler.rb +55 -0
  25. data/lib/vigilem/core/lockable_pipeline_component.rb +30 -0
  26. data/lib/vigilem/core/multiplexer.rb +168 -0
  27. data/lib/vigilem/core/pipeline.rb +68 -0
  28. data/lib/vigilem/core/stat.rb +121 -0
  29. data/lib/vigilem/core/system.rb +9 -0
  30. data/lib/vigilem/core/system/check.rb +33 -0
  31. data/lib/vigilem/core/transfer_agent.rb +67 -0
  32. data/lib/vigilem/core/version.rb +5 -0
  33. data/spec/bug_notes.txt +12 -0
  34. data/spec/given_helper.rb +12 -0
  35. data/spec/spec_helper.rb +7 -0
  36. data/spec/vigilem/core/abstract_device_spec.rb +103 -0
  37. data/spec/vigilem/core/adapters/adapter_spec.rb +28 -0
  38. data/spec/vigilem/core/adapters/basic_adapter_spec.rb +53 -0
  39. data/spec/vigilem/core/adapters/buffered_adapter_spec.rb +16 -0
  40. data/spec/vigilem/core/buffer_handler_spec.rb +51 -0
  41. data/spec/vigilem/core/buffer_spec.rb +236 -0
  42. data/spec/vigilem/core/default_buffer_spec.rb +17 -0
  43. data/spec/vigilem/core/demultiplexer_spec.rb +166 -0
  44. data/spec/vigilem/core/device_spec.rb +62 -0
  45. data/spec/vigilem/core/event_handler_spec.rb +134 -0
  46. data/spec/vigilem/core/hooks/callback_proc_spec.rb +66 -0
  47. data/spec/vigilem/core/hooks/hook_spec.rb +230 -0
  48. data/spec/vigilem/core/hooks/inheritable_spec.rb +19 -0
  49. data/spec/vigilem/core/hooks/meta_callback_spec.rb +69 -0
  50. data/spec/vigilem/core/hooks/utils_spec.rb +25 -0
  51. data/spec/vigilem/core/hooks_spec.rb +50 -0
  52. data/spec/vigilem/core/hub_spec.rb +51 -0
  53. data/spec/vigilem/core/input_system_handler_spec.rb +33 -0
  54. data/spec/vigilem/core/lockable_pipeline_component_spec.rb +19 -0
  55. data/spec/vigilem/core/multiplexer_spec.rb +113 -0
  56. data/spec/vigilem/core/pipeline_spec.rb +5 -0
  57. data/spec/vigilem/core/stat_spec.rb +63 -0
  58. data/spec/vigilem/core/system/check_spec.rb +24 -0
  59. data/spec/vigilem/core/system_spec.rb +29 -0
  60. data/spec/vigilem/core/transfer_agent_spec.rb +80 -0
  61. metadata +273 -0
@@ -0,0 +1,45 @@
1
+ require 'delegate'
2
+
3
+ require 'vigilem/core/buffer'
4
+
5
+ module Vigilem
6
+ module Core
7
+ #
8
+ class DefaultBuffer < ::SimpleDelegator
9
+ include Buffer
10
+
11
+ #
12
+ # @param [#slice!] type
13
+ def initialize(type=[])
14
+ super(type)
15
+ end
16
+
17
+ # like new except type is not optional
18
+ # and passes through an object that is
19
+ # already of self type
20
+ # @param type
21
+ # @return [DefaultBuffer]
22
+ def self.wrap(type)
23
+ if type.is_a? self
24
+ type
25
+ else
26
+ new(type)
27
+ end
28
+ end
29
+
30
+ #
31
+ # @param other_obj
32
+ # @return [TrueClass || FalseClass]
33
+ def ==(other_obj)
34
+ super(other_obj) ||
35
+ __getobj__ == other_obj.respond.__getobj__
36
+ end
37
+
38
+ #
39
+ # @return [String]
40
+ def inspect
41
+ "#<#{self.class}:0x#{object_id} #{super}>"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,225 @@
1
+ require 'observer'
2
+
3
+ require 'thread_safe'
4
+
5
+ require 'vigilem/support/core_ext'
6
+
7
+ require 'vigilem/support/obj_space'
8
+
9
+ require 'vigilem/support/lazy_simple_delegator'
10
+
11
+ require 'vigilem/core/multiplexer'
12
+
13
+ module Vigilem
14
+ module Core
15
+ # #shift's from input and distributes it to the
16
+ # observers
17
+ class Demultiplexer
18
+ include Observable
19
+
20
+ extend Support::ObjSpace
21
+
22
+ attr_accessor :input
23
+
24
+ alias_method :source, :input
25
+ alias_method :source=, :input=
26
+
27
+ #
28
+ # @param [Array<Array<observer_object, Hash{@see #add_observer}>>] observers
29
+ # @param [(Buffer) #slice!] input_source
30
+ def self.new(input_source=nil, observers=[])
31
+ obj_register(super(input_source, observers))
32
+ end
33
+
34
+ #
35
+ # @param [Array<Array<observer_object, Hash{@see #add_observer}>>] observers
36
+ # @param [(Buffer) #shift] input_source
37
+ def initialize(input_source=nil, observers=[])
38
+ @input = input_source
39
+
40
+ add_observers(observers)
41
+ end
42
+
43
+ # the peers without the Delegators
44
+ # @return [Array]
45
+ def observers
46
+ _observers.map {|obj| obj.respond(:peel) || obj }
47
+ end
48
+
49
+ alias_method :outputs, :observers
50
+
51
+ #
52
+ # @return [Array]
53
+ def _observers
54
+ (@observer_peers ||= ThreadSafe::Hash.new).keys
55
+ end
56
+
57
+ alias_method :_outputs, :_observers
58
+
59
+ # @see Observable#add_observer
60
+ # @param [Hash] event_opts
61
+ # @option :func
62
+ # @option :type [Integer]
63
+ # @option :types [Array<Integer>]
64
+ # @option :device_name [Regexp]
65
+ # @option :device_names [Array<Regexp>]
66
+ # @option :device [File]
67
+ # @option :devices [Array<File>]
68
+ # @return [Array] [event_opts]
69
+ def add_observer(observer, event_opts={})
70
+ observer = Support::LazySimpleDelegator.new(observer).use_strict_eql if observer.is_a? Array
71
+ _observers
72
+ unless observer.respond_to?(event_opts[:func] ||= :update)
73
+ raise NoMethodError, "observer does not respond to `#{func.to_s}'"
74
+ end
75
+ @observer_peers[observer] = event_opts
76
+ end
77
+
78
+ alias_method :add_output, :add_observer
79
+
80
+ # @see Observable#add_observer
81
+ # @param [Array<Array<observer_object, Hash{@see add_observer}>>]
82
+ # @return [Array]
83
+ def add_observers(observers_and_opts)
84
+ observers_and_opts.map do |(obs, hsh)|
85
+ add_observer(*[obs, hsh].compact)
86
+ end
87
+ end
88
+
89
+ alias_method :add_outputs, :add_observers
90
+
91
+ #
92
+ # @see Object#inspect
93
+ # @return [String]
94
+ def inspect
95
+ if input.is_a? Array # @todo switch from regex
96
+ super.gsub(/@input=.+?(\s+|>)/, "@input=#<#{input.class}:#{Support::Utils.inspect_id(input)} #{input}>\\1")
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ #
103
+ # @return [Monitor]
104
+ def semaphore
105
+ if defined? super
106
+ super
107
+ else
108
+ @semaphore ||= Monitor.new
109
+ end
110
+ end
111
+
112
+ # gets events from input and notifies_observers
113
+ # @param [Integer] max_number_of_events
114
+ # @return
115
+ def demux(max_number_of_events=1)
116
+ semaphore.synchronize {
117
+ events = input.shift(max_number_of_events)
118
+ changed
119
+ notify_observers(*events)
120
+ }
121
+ end
122
+
123
+ #
124
+ # @see Observable#notify_observers
125
+ # @param [Array]
126
+ # @return [TrueClass || FalseClass]
127
+ def notify_observers(*events)
128
+ if defined? @observer_state and @observer_state
129
+ if defined? @observer_peers
130
+ @observer_peers.each do |k, event_opts|
131
+ filtered = self.class.filter_events(events, event_opts)
132
+ k.send event_opts[:func], filtered unless filtered.empty?
133
+ end
134
+ end
135
+ @observer_state = false
136
+ end
137
+ end
138
+
139
+ alias_method :sweep, :notify_observers
140
+ alias_method :notify_outputs, :notify_observers
141
+
142
+ #
143
+ # @param [Array] events
144
+ # @param [Hash{@see #add_observer}] event_opts
145
+ # @return [Array]
146
+ def filter_events(events, event_opts)
147
+ self.class.filter_events(events, event_opts)
148
+ end
149
+
150
+ class << self
151
+
152
+ #
153
+ # @param base
154
+ # @return
155
+ def inherited(base)
156
+ base.extend Support::ObjSpace
157
+ end
158
+
159
+ #
160
+ # @param [Array<#metadata, #type>] events
161
+ # @param [Hash{@see #add_observer}] event_opts
162
+ # @return [Array]
163
+ def filter_events(events, event_opts)
164
+ events.select do |event|
165
+ opts = event_opts.select {|k,v| event_option_names.include? k }
166
+ if opts.empty?
167
+ event
168
+ else
169
+ opts.all? do |opt,v|
170
+ opt_vals = [v].flatten
171
+ case opt.to_s
172
+ when /^devices?$/
173
+ opt_vals.any? do |dev|
174
+ if (src = event.metadata[:source])
175
+ File.identical?(dev, src)
176
+ end
177
+ end
178
+ when /^device_names?$/
179
+ opt_vals.any? {|dev_name| event.metadata[:source].respond.name =~ dev_name }
180
+ when /^types?$/
181
+ opt_vals.any? {|ev_type| event.type == ev_type }
182
+ end
183
+ end
184
+
185
+ end # else
186
+
187
+ end
188
+ end
189
+
190
+ # like first_or_new
191
+ # @return [Demultiplexer]
192
+ def acquire(input_source=nil, observers=[], &block)
193
+ found = all.find(&block)
194
+ if found
195
+ found.add_observers(observers)
196
+ else
197
+ new(input_source, observers)
198
+ end
199
+ end
200
+
201
+ #
202
+ # @return [Hash]
203
+ def same_source_check
204
+ all.group_by do |dem|
205
+ dem.respond(:fileno) || dem
206
+ end.select {|k, v| v.size > 1 }
207
+ end
208
+
209
+ #
210
+ # @return [Array<Symbol>]
211
+ def event_option_names
212
+ @event_option_names ||= option_names - [:func]
213
+ end
214
+
215
+ #
216
+ # @return [Array<Symbol>]
217
+ def option_names
218
+ @options ||= [:func, :type, :types, :device_name, :device_names, :device, :devices]
219
+ end
220
+
221
+ end
222
+ end
223
+
224
+ end
225
+ end
@@ -0,0 +1,43 @@
1
+ require 'vigilem/core/abstract_device'
2
+
3
+ require 'vigilem/core/hooks'
4
+
5
+ require 'vigilem/core/system'
6
+
7
+ module Vigilem
8
+ module Core
9
+ #
10
+ # hooks for loading the pipeline
11
+ # errors when no :system_check has passed
12
+ # @todo more configurable facade so not all methods from
13
+ # underlying object get through
14
+ class Device < AbstractDevice
15
+
16
+ #
17
+ # @param [Array] args
18
+ # @param [Proc] config
19
+ # @return
20
+ def self.new(*args, &config)
21
+ if block_given?
22
+ (ret = Class.new(self)).instance_eval(&config)
23
+ ret
24
+ else
25
+ super(*args)
26
+ end
27
+ end
28
+
29
+ Hooks::ConditionalHook.new(:on_os, :type => :system_check) do
30
+ condition {|name_or_regex| System.check[:os].call(name_or_regex) }
31
+ end.bind(self)
32
+
33
+ Hooks::ConditionalHook.new(:on_input_system, :type => :system_check) do
34
+ condition {|name_or_regex| System.check[:input_system].call(name_or_regex) }
35
+ end.bind(self)
36
+
37
+ after_init do |dev|
38
+ raise 'Device not compatible on this system' unless dev.available?
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,156 @@
1
+ require 'forwardable'
2
+
3
+ require 'active_support/concern'
4
+
5
+ module Vigilem
6
+ module Core
7
+ #
8
+ #
9
+ module EventHandler
10
+
11
+ extend Forwardable
12
+
13
+ extend ActiveSupport::Concern
14
+
15
+ #
16
+ #
17
+ module Utils
18
+
19
+ #
20
+ # @param [#to_s] namespace
21
+ # @return [String]
22
+ def snakecase_class_name(namespace)
23
+ namespace.to_s.split('::').last.snakecase
24
+ end
25
+
26
+ #
27
+ # @param [Symbol] sym
28
+ # @return [TrueClass || FalseClass]
29
+ def respond_to?(sym, include_all=false)
30
+ on_format?(sym.to_s) || super(sym, include_all)
31
+ end
32
+
33
+ # does the string passed in start with 'on_'
34
+ # @param [String] str
35
+ # @return [TrueClass || FalseClass]
36
+ def on_format?(str)
37
+ str.start_with?('on_')
38
+ end
39
+
40
+ # converts a "on_String" => :String
41
+ # @param [String] on_name
42
+ # @return [Symbol]
43
+ def type_from_on_format(on_name)
44
+ on_name.split('on_', 2).last.to_sym
45
+ end
46
+ end
47
+
48
+ include Utils
49
+ extend Utils
50
+
51
+ module ClassMethods
52
+
53
+ include Utils
54
+
55
+ # @todo Fuzzy is_a? Hash key lookup
56
+ # @return [Hash]
57
+ def type_handles
58
+ @type_handles ||= {}
59
+ end
60
+
61
+ #
62
+ # sets the default_handler, if called without a block, just
63
+ # assigns the default handler to a "default"
64
+ # @param [Proc] block
65
+ # @return [Proc]
66
+ def default_handler(&block)
67
+ type_handles.default = (block || lambda {|*args, &block| })
68
+ end
69
+
70
+ # @todo module_function
71
+ # configures how this event handler handles an event
72
+ # @param type
73
+ # @return [Proc] the block given/registered
74
+ def on(type, opts={}, &block)
75
+ type_name = snakecase_class_name(type)
76
+ on_method = send(:_define_register, type, type_name)
77
+ type_handles[type] = send(:_define_handler, type_name, &block)
78
+ on_method.call(&block)
79
+ end
80
+
81
+ alias_method :register_handle, :on
82
+
83
+ private
84
+
85
+ # defines `on_#{event_type}'
86
+ # @param type
87
+ # @param [String] type_name
88
+ # @param [Proc] block
89
+ # @return [Method]
90
+ def _define_register(type, type_name)
91
+ define_singleton_method(on_method_name = :"on_#{type_name}") {|opts={}, &blk| type_handles[type] = blk }
92
+ define_method(on_method_name) {|opts={}, &blk| self.class.send(on_method_name, opts, &blk) }
93
+ method(on_method_name)
94
+ end
95
+
96
+ # defines `handle_#{event_type}'
97
+ # @param [String] type
98
+ # @param [Proc] block
99
+ # @return [Proc]
100
+ def _define_handler(type_name, &block)
101
+ define_method(handler_name = :"handle_#{type_name}", &block)
102
+ block
103
+ end
104
+
105
+ end
106
+
107
+ #
108
+ # @return [Hash]
109
+ def type_handles
110
+ self.class.type_handles
111
+ end
112
+
113
+ # to trigger the handling, either use handle(event, opts={}) or handle_#{type}
114
+ # configures how this event handler handles an event
115
+ # @param [#to_s] type
116
+ # @return [Proc] the block given/registered
117
+ def on(type, &block)
118
+ define_singleton_method(on_method_name = :"on_#{class_name = snakecase_class_name(type)}") {|&blk| type_handles[type] = blk }
119
+ ret = send on_method_name, &block
120
+ define_singleton_method(handler_name = :"handle_#{class_name}", &type_handles[type])
121
+ ret
122
+ end
123
+ alias_method :register_handle, :on
124
+
125
+ #
126
+ # @param event, the event to handle
127
+ # @param [Array]
128
+ # @return results of the Proc registered to the type_handless
129
+ def handle(event, *args, &block)
130
+ if handler = type_handles[event.class]
131
+ handler.call(event, *args, &block)
132
+ end
133
+ end
134
+
135
+ #
136
+ # @param event, the event to handle
137
+ # @param [Array]
138
+ # @return results of the Proc registered to the type_handless
139
+ def handle!(event, *args, &block)
140
+ if ret = handle(event, *args, &block)
141
+ ret
142
+ else
143
+ raise NotImplementedError, "No handler found for #{key.class}:#{key},#{block} and no default handler set"
144
+ end
145
+ end
146
+
147
+ #
148
+ # @param [Proc]
149
+ # @return
150
+ def default_handler(&block)
151
+ self.class.default_handler(&block)
152
+ end
153
+
154
+ end
155
+ end
156
+ end