ztk 1.0.0.rc.0 → 1.0.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,6 +30,13 @@ module ZTK
30
30
  #
31
31
  # This class can be used to easily run a linear process in a background manner.
32
32
  #
33
+ # The before fork callback is called once in the parent process.
34
+ #
35
+ # The after fork callback is called twice, once in the parent process and once
36
+ # in the child process.
37
+ #
38
+ # *example code*:
39
+ #
33
40
  # a_callback = Proc.new do |pid|
34
41
  # puts "Hello from After Callback - PID #{pid}"
35
42
  # end
@@ -44,17 +51,53 @@ module ZTK
44
51
  # config.after_fork = a_callback
45
52
  # end
46
53
  #
47
- # background.process do
48
- # x
54
+ # pid = background.process do
55
+ # sleep(1)
49
56
  # end
57
+ # puts pid.inspect
50
58
  #
51
59
  # background.wait
52
- # background.result
60
+ # puts background.result.inspect
53
61
  #
54
- # The before fork callback is called once in the parent process.
62
+ # *pry output*:
55
63
  #
56
- # The after fork callback is called twice, once in the parent process and once
57
- # in the child process.
64
+ # [1] pry(main)> a_callback = Proc.new do |pid|
65
+ # [1] pry(main)* puts "Hello from After Callback - PID #{pid}"
66
+ # [1] pry(main)* end
67
+ # => #<Proc:0x00000001368a98@(pry):1>
68
+ # [2] pry(main)>
69
+ # [3] pry(main)> b_callback = Proc.new do |pid|
70
+ # [3] pry(main)* puts "Hello from Before Callback - PID #{pid}"
71
+ # [3] pry(main)* end
72
+ # => #<Proc:0x00000001060418@(pry):4>
73
+ # [4] pry(main)>
74
+ # [5] pry(main)> background = ZTK::Background.new
75
+ # => #<ZTK::Background:0x00000001379118
76
+ # @config=
77
+ # #<OpenStruct stdout=#<IO:<STDOUT>>, stderr=#<IO:<STDERR>>, stdin=#<IO:<STDIN>>, logger=#<ZTK::Logger filename="/dev/null">>,
78
+ # @result=nil>
79
+ # [6] pry(main)> background.config do |config|
80
+ # [6] pry(main)* config.before_fork = b_callback
81
+ # [6] pry(main)* config.after_fork = a_callback
82
+ # [6] pry(main)* end
83
+ # => #<Proc:0x00000001368a98@(pry):1>
84
+ # [7] pry(main)>
85
+ # [8] pry(main)> pid = background.process do
86
+ # [8] pry(main)* sleep(1)
87
+ # [8] pry(main)* end
88
+ # Hello from Before Callback - PID 23564
89
+ # Hello from After Callback - PID 23564
90
+ # Hello from After Callback - PID 23578
91
+ # => 23578
92
+ # [9] pry(main)> puts pid.inspect
93
+ # 23578
94
+ # => nil
95
+ # [10] pry(main)>
96
+ # [11] pry(main)> background.wait
97
+ # => [23578, #<Process::Status: pid 23578 exit 0>, 1]
98
+ # [12] pry(main)> puts background.result.inspect
99
+ # 1
100
+ # => nil
58
101
  #
59
102
  # @author Zachary Patten <zachary@jovelabs.net>
60
103
  class Background < ZTK::Base
@@ -66,7 +109,7 @@ module ZTK
66
109
  def initialize(configuration={})
67
110
  super({
68
111
  }.merge(configuration))
69
- config.logger.debug { "config=#{config.send(:table).inspect}" }
112
+ config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
70
113
 
71
114
  @result = nil
72
115
  GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
@@ -96,7 +139,7 @@ module ZTK
96
139
  STDIN.reopen("/dev/null")
97
140
 
98
141
  if !(data = block.call).nil?
99
- config.logger.debug { "write(#{data.inspect})" }
142
+ config.ui.logger.debug { "write(#{data.inspect})" }
100
143
  @child_writer.write(Base64.encode64(Marshal.dump(data)))
101
144
  end
102
145
 
@@ -125,11 +168,11 @@ module ZTK
125
168
  # status and data returned from the process block. If wait2() fails nil
126
169
  # is returned.
127
170
  def wait
128
- config.logger.debug { "wait" }
171
+ config.ui.logger.debug { "wait" }
129
172
  pid, status = (Process.wait2(@pid) rescue nil)
130
173
  if !pid.nil? && !status.nil?
131
174
  data = (Marshal.load(Base64.decode64(@parent_reader.read.to_s)) rescue nil)
132
- config.logger.debug { "read(#{data.inspect})" }
175
+ config.ui.logger.debug { "read(#{data.inspect})" }
133
176
  !data.nil? and @result = data
134
177
 
135
178
  @parent_reader.close
data/lib/ztk/base.rb CHANGED
@@ -22,6 +22,8 @@ require "ostruct"
22
22
  module ZTK
23
23
 
24
24
  # ZTK::Base Error Class
25
+ #
26
+ # @author Zachary Patten <zachary@jovelabs.net>
25
27
  class BaseError < Error; end
26
28
 
27
29
  # ZTK Base Class
@@ -32,34 +34,25 @@ module ZTK
32
34
  #
33
35
  # You should never interact with this class directly; you should inherit it
34
36
  # and extend functionality as appropriate.
37
+ #
38
+ # @author Zachary Patten <zachary@jovelabs.net>
35
39
  class Base
36
40
 
37
41
  class << self
38
42
 
39
43
  # @param [Hash] configuration Configuration options hash.
40
- # @option config [IO] :stdout Instance of IO to be used for STDOUT.
41
- # @option config [IO] :stderr Instance of IO to be used for STDERR.
42
- # @option config [IO] :stdin Instance of IO to be used for STDIN.
43
- # @option config [Logger] :logger Instance of Logger to be used for logging.
44
+ # @option config [ZTK::UI] :ui Instance of ZTK:UI to be used for
45
+ # console IO and logging.
44
46
  def build_config(configuration={})
45
47
  if configuration.is_a?(OpenStruct)
46
48
  configuration = configuration.send(:table)
47
49
  end
48
50
 
49
- rails_logger = Rails.logger if defined?(Rails)
50
-
51
+ # FIXME: this needs to be refactored into the UI class
51
52
  config = OpenStruct.new({
52
- :stdout => $stdout,
53
- :stderr => $stderr,
54
- :stdin => $stdin,
55
- :logger => ($logger || rails_logger || ZTK::Logger.new("/dev/null"))
53
+ :ui => ::ZTK::UI.new
56
54
  }.merge(configuration))
57
55
 
58
- (config.stdout && config.stdout.respond_to?(:sync=)) and config.stdout.sync = true
59
- (config.stderr && config.stderr.respond_to?(:sync=)) and config.stderr.sync = true
60
- (config.stdin && config.stdin.respond_to?(:sync=)) and config.stdin.sync = true
61
- (config.logger && config.logger.respond_to?(:sync=)) and config.logger.sync = true
62
-
63
56
  config
64
57
  end
65
58
 
@@ -133,7 +126,7 @@ module ZTK
133
126
  # @param [Integer] shift (2) How many places to shift the caller stack in
134
127
  # the log statement.
135
128
  def log_and_raise(exception, message, shift=2)
136
- Base.log_and_raise(config.logger, exception, message, shift)
129
+ Base.log_and_raise(config.ui.logger, exception, message, shift)
137
130
  end
138
131
 
139
132
  # Direct logging method.
@@ -149,17 +142,17 @@ module ZTK
149
142
  # @yield No value is passed to the block.
150
143
  # @yieldreturn [String] The message to log.
151
144
  def direct_log(log_level, &blocK)
152
- @config.logger.nil? and raise BaseError, "You must supply a logger for direct logging support!"
145
+ @config.ui.logger.nil? and raise BaseError, "You must supply a logger for direct logging support!"
153
146
 
154
147
  if !block_given?
155
148
  log_and_raise(BaseError, "You must supply a block to the log method!")
156
- elsif (@config.logger.level <= ZTK::Logger.const_get(log_level.to_s.upcase))
157
- if @config.logger.respond_to?(:logdev)
158
- @config.logger.logdev.write(yield)
159
- @config.logger.logdev.respond_to?(:flush) and @config.logger.logdev.flush
149
+ elsif (@config.ui.logger.level <= ZTK::Logger.const_get(log_level.to_s.upcase))
150
+ if @config.ui.logger.respond_to?(:logdev)
151
+ @config.ui.logger.logdev.write(yield)
152
+ @config.ui.logger.logdev.respond_to?(:flush) and @config.ui.logger.logdev.flush
160
153
  else
161
- @config.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).write(yield)
162
- @config.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).respond_to?(:flush) and @config.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).flush
154
+ @config.ui.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).write(yield)
155
+ @config.ui.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).respond_to?(:flush) and @config.ui.logger.instance_variable_get(:@logdev).instance_variable_get(:@dev).flush
163
156
  end
164
157
  end
165
158
  end
data/lib/ztk/benchmark.rb CHANGED
@@ -35,6 +35,26 @@ module ZTK
35
35
  # the appropriate options it will display output to the user while
36
36
  # benchmarking the supplied block.
37
37
  #
38
+ # *example code*:
39
+ #
40
+ # message = "I wonder how long this will take?"
41
+ # mark = " ...looks like it took %0.4f seconds!"
42
+ # ZTK::Benchmark.bench(:message => message, :mark => mark) do
43
+ # sleep(1.5)
44
+ # end
45
+ #
46
+ # *pry output*:
47
+ #
48
+ # [1] pry(main)> message = "I wonder how long this will take?"
49
+ # => "I wonder how long this will take?"
50
+ # [2] pry(main)> mark = " ...looks like it took %0.4f seconds!"
51
+ # => " ...looks like it took %0.4f seconds!"
52
+ # [3] pry(main)> ZTK::Benchmark.bench(:message => message, :mark => mark) do
53
+ # [3] pry(main)* sleep(1.5)
54
+ # [3] pry(main)* end
55
+ # I wonder how long this will take? ...looks like it took 1.5229 seconds!
56
+ # => 1.522871547
57
+ #
38
58
  # @author Zachary Patten <zachary@jovelabs.net>
39
59
  class Benchmark
40
60
 
@@ -61,23 +81,31 @@ module ZTK
61
81
  # after the block is yielded. This *String* should have an *sprintf*
62
82
  # floating point macro in it if the benchmark is desired to be embedded
63
83
  # in the given *String*.
84
+ # @option options [Boolean] :use_spinner (true) Weither or not to use the
85
+ # ZTK::Spinner while benchmarking.
64
86
  #
65
87
  # @yield Block should execute the tasks to be benchmarked.
66
88
  # @yieldreturn [Object] The return value of the block is ignored.
67
89
  # @return [Float] The benchmark time.
68
90
  def bench(options={}, &block)
69
- options = Base.build_config(options)
70
- options.logger.debug { "options=#{options.send(:table).inspect}" }
91
+ options = Base.build_config({
92
+ :use_spinner => true
93
+ }.merge(options))
94
+ options.ui.logger.debug { "options=#{options.send(:table).inspect}" }
71
95
 
72
- !block_given? and Base.log_and_raise(options.logger, BenchmarkError, "You must supply a block!")
96
+ !block_given? and Base.log_and_raise(options.ui.logger, BenchmarkError, "You must supply a block!")
73
97
 
74
98
  check = [options.message, options.mark]
75
- (check.any?{ |z| !z.nil? } && !check.all?{ |z| !z.nil? }) and Base.log_and_raise(options.logger, BenchmarkError, "You must supply both a message and a mark!")
99
+ (check.any?{ |z| !z.nil? } && !check.all?{ |z| !z.nil? }) and Base.log_and_raise(options.ui.logger, BenchmarkError, "You must supply both a message and a mark!")
76
100
 
77
- (options.message && options.mark) and options.stdout.print("#{options.message} ")
101
+ (options.message && options.mark) and options.ui.stdout.print("#{options.message} ")
78
102
  benchmark = ::Benchmark.realtime do
79
103
  if (options.message && options.mark)
80
- ZTK::Spinner.spin(Base.sanitize_config(options)) do
104
+ if options.use_spinner
105
+ ZTK::Spinner.spin(Base.sanitize_config(options)) do
106
+ yield
107
+ end
108
+ else
81
109
  yield
82
110
  end
83
111
  else
@@ -85,8 +113,8 @@ module ZTK
85
113
  end
86
114
  end
87
115
 
88
- (options.message && options.mark) and options.stdout.print("#{options.mark}\n" % benchmark)
89
- options.logger.info { "#{options.message} #{options.mark}" % benchmark }
116
+ (options.message && options.mark) and options.ui.stdout.print("#{options.mark}\n" % benchmark)
117
+ options.ui.logger.info { "#{options.message} #{options.mark}" % benchmark }
90
118
 
91
119
  benchmark
92
120
  end
data/lib/ztk/command.rb CHANGED
@@ -46,7 +46,7 @@ module ZTK
46
46
  :timeout => 600,
47
47
  :ignore_exit_status => false
48
48
  }.merge(configuration))
49
- config.logger.debug { "config=#{config.send(:table).inspect}" }
49
+ config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
50
50
  end
51
51
 
52
52
  # Executes a local command.
@@ -65,12 +65,12 @@ module ZTK
65
65
  def exec(command, options={})
66
66
  options = OpenStruct.new({ :exit_code => 0, :silence => false }.merge(options))
67
67
 
68
- config.logger.debug { "config=#{config.send(:table).inspect}" }
69
- config.logger.debug { "options=#{options.send(:table).inspect}" }
70
- config.logger.info { "command(#{command.inspect})" }
68
+ config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
69
+ config.ui.logger.debug { "options=#{options.send(:table).inspect}" }
70
+ config.ui.logger.info { "command(#{command.inspect})" }
71
71
 
72
72
  if config.replace_current_process
73
- config.logger.fatal { "REPLACING CURRENT PROCESS - GOODBYE!" }
73
+ config.ui.logger.fatal { "REPLACING CURRENT PROCESS - GOODBYE!" }
74
74
  Kernel.exec(command)
75
75
  end
76
76
 
@@ -101,7 +101,7 @@ module ZTK
101
101
  child_stderr_writer.close
102
102
 
103
103
  reader_writer_key = {parent_stdout_reader => :stdout, parent_stderr_reader => :stderr}
104
- reader_writer_map = {parent_stdout_reader => @config.stdout, parent_stderr_reader => @config.stderr}
104
+ reader_writer_map = {parent_stdout_reader => @config.ui.stdout, parent_stderr_reader => @config.ui.stderr}
105
105
 
106
106
  direct_log(:debug) { log_header("COMMAND") }
107
107
  direct_log(:debug) { "#{command}\n" }
@@ -152,7 +152,7 @@ module ZTK
152
152
  parent_stdout_reader.close
153
153
  parent_stderr_reader.close
154
154
 
155
- config.logger.debug { "exit_code(#{exit_code})" }
155
+ config.ui.logger.debug { "exit_code(#{exit_code})" }
156
156
 
157
157
  if !config.ignore_exit_status && (exit_code != options.exit_code)
158
158
  log_and_raise(CommandError, "exec(#{command.inspect}, #{options.inspect}) failed! [#{exit_code}]")
data/lib/ztk/dsl.rb CHANGED
@@ -17,11 +17,14 @@
17
17
  # limitations under the License.
18
18
  #
19
19
  ################################################################################
20
-
21
20
  require "active_support/inflector"
22
21
 
23
- # @author Zachary Patten <zachary@jovelabs.net>
24
22
  module ZTK
23
+
24
+ # Generic Domain-specific Language Interface
25
+ #
26
+ # @see ZTK::DSL::Base
27
+ # @author Zachary Patten <zachary@jovelabs.net>
25
28
  module DSL
26
29
 
27
30
  # @author Zachary Patten <zachary@jovelabs.net>
data/lib/ztk/dsl/base.rb CHANGED
@@ -18,12 +18,141 @@
18
18
  #
19
19
  ################################################################################
20
20
 
21
- # @author Zachary Patten <zachary@jovelabs.net>
22
21
  module ZTK::DSL
23
22
 
23
+ # Generic Domain-specific Language Interface
24
+ #
25
+ # This module allows you to easily add attributes and relationships to classes
26
+ # to create a custom DSL in no time.
27
+ #
28
+ # You can then access these classes in manners similar to what *ActiveRecord*
29
+ # provides for relationships. You can easily link classes together; load
30
+ # stored objects from Ruby rb files (think Opscode Chef DSL).
31
+ #
32
+ # I intend the interface to act like ActiveRecord for the programmer and a
33
+ # nice DSL for the end user. It's not meant to be a database; more like
34
+ # a soft dataset in memory; extremely fast but highly volitale. As always
35
+ # you can never have your cake and eat it too.
36
+ #
37
+ # You specify the "schema" in the classes itself; there is no data storage at
38
+ # this time, but I do plan to add support for loading/saving *datasets* to
39
+ # disk. Keep in mind since you do not specify type constrants in Ruby, one
40
+ # can assign any object to an attribute.
41
+ #
42
+ # At this time if you do not specify an ID; one is auto generated.
43
+ #
44
+ # If you wish to create objects in a nested fashion the outer most object must
45
+ # be started using the class name initializer. Once inside the block you can
46
+ # start using the relationship names and do not need to call any further
47
+ # class initializers.
48
+ #
49
+ # You can also instantiate classes separately and associate them after the
50
+ # fact. That is not shown in this example.
51
+ #
52
+ # *example code*:
53
+ #
54
+ # class Network < ZTK::DSL::Base
55
+ # has_many :servers
56
+ #
57
+ # attribute :name
58
+ # attribute :gw
59
+ # attribute :network
60
+ # attribute :netmask
61
+ # end
62
+ #
63
+ # class Server < ZTK::DSL::Base
64
+ # belongs_to :network
65
+ #
66
+ # attribute :name
67
+ # end
68
+ #
69
+ # Network.new do
70
+ # id :leet_net
71
+ # name "leet-net"
72
+ # gw "7.3.3.1"
73
+ # network "7.3.3.0"
74
+ # netmask "255.255.255.0"
75
+ #
76
+ # server do
77
+ # name "leet-server"
78
+ # end
79
+ #
80
+ # server do
81
+ # id :my_server
82
+ # name "my-server"
83
+ # end
84
+ #
85
+ # server do
86
+ # name "dev-server"
87
+ # end
88
+ # end
89
+ #
90
+ # Network.count
91
+ # Network.all
92
+ # Network.find(:leet_net)
93
+ #
94
+ # Server.count
95
+ # Server.all
96
+ # Server.find(:my_server)
97
+ #
98
+ # *pry output*:
99
+ #
100
+ # [1] pry(main)> class Network < ZTK::DSL::Base
101
+ # [1] pry(main)* has_many :servers
102
+ # [1] pry(main)*
103
+ # [1] pry(main)* attribute :name
104
+ # [1] pry(main)* attribute :gw
105
+ # [1] pry(main)* attribute :network
106
+ # [1] pry(main)* attribute :netmask
107
+ # [1] pry(main)* end
108
+ # => #<Proc:0x0000000121f498@/home/zpatten/Dropbox/code/chef-repo/vendor/checkouts/ztk/lib/ztk/dsl/core/attributes.rb:45 (lambda)>
109
+ # [2] pry(main)> class Server < ZTK::DSL::Base
110
+ # [2] pry(main)* belongs_to :network
111
+ # [2] pry(main)*
112
+ # [2] pry(main)* attribute :name
113
+ # [2] pry(main)* end
114
+ # => #<Proc:0x00000001983108@/home/zpatten/Dropbox/code/chef-repo/vendor/checkouts/ztk/lib/ztk/dsl/core/attributes.rb:45 (lambda)>
115
+ # [3] pry(main)> Network.new do
116
+ # [3] pry(main)* id :leet_net
117
+ # [3] pry(main)* name "leet-net"
118
+ # [3] pry(main)* gw "7.3.3.1"
119
+ # [3] pry(main)* network "7.3.3.0"
120
+ # [3] pry(main)* netmask "255.255.255.0"
121
+ # [3] pry(main)*
122
+ # [3] pry(main)* server do
123
+ # [3] pry(main)* name "leet-server"
124
+ # [3] pry(main)* end
125
+ # [3] pry(main)*
126
+ # [3] pry(main)* server do
127
+ # [3] pry(main)* id :my_server
128
+ # [3] pry(main)* name "my-server"
129
+ # [3] pry(main)* end
130
+ # [3] pry(main)*
131
+ # [3] pry(main)* server do
132
+ # [3] pry(main)* name "dev-server"
133
+ # [3] pry(main)* end
134
+ # [3] pry(main)* end
135
+ # => #<Network id=:leet_net attributes={:id=>:leet_net, :name=>"leet-net", :gw=>"7.3.3.1", :network=>"7.3.3.0", :netmask=>"255.255.255.0"}, has_many_references=1>
136
+ # [4] pry(main)> Network.count
137
+ # => 1
138
+ # [5] pry(main)> Network.all
139
+ # => [#<Network id=:leet_net attributes={:id=>:leet_net, :name=>"leet-net", :gw=>"7.3.3.1", :network=>"7.3.3.0", :netmask=>"255.255.255.0"}, has_many_references=1>]
140
+ # [6] pry(main)> Network.find(:leet_net)
141
+ # => [#<Network id=:leet_net attributes={:id=>:leet_net, :name=>"leet-net", :gw=>"7.3.3.1", :network=>"7.3.3.0", :netmask=>"255.255.255.0"}, has_many_references=1>]
142
+ # [7] pry(main)> Server.count
143
+ # => 3
144
+ # [8] pry(main)> Server.all
145
+ # => [#<Server id=2 attributes={:id=>2, :name=>"leet-server", :network_id=>:leet_net}, belongs_to_references=1>,
146
+ # #<Server id=:my_server attributes={:id=>:my_server, :name=>"my-server", :network_id=>:leet_net}, belongs_to_references=1>,
147
+ # #<Server id=4 attributes={:id=>4, :name=>"dev-server", :network_id=>:leet_net}, belongs_to_references=1>]
148
+ # [9] pry(main)> Server.find(:my_server)
149
+ # => [#<Server id=:my_server attributes={:id=>:my_server, :name=>"my-server", :network_id=>:leet_net}, belongs_to_references=1>]
150
+ #
151
+ # @author Zachary Patten <zachary@jovelabs.net>
24
152
  class Base
25
153
  include(ZTK::DSL::Core)
26
154
 
155
+ # @api private
27
156
  def self.inherited(base)
28
157
  puts("inherited(#{base})")
29
158
  base.send(:extend, ZTK::DSL::Base::ClassMethods)
@@ -32,10 +161,12 @@ module ZTK::DSL
32
161
  end
33
162
  end
34
163
 
164
+ # @api private
35
165
  def self.included(base)
36
166
  puts("included(#{base})")
37
167
  end
38
168
 
169
+ # @api private
39
170
  def self.extended(base)
40
171
  puts("extended(#{base})")
41
172
  end
@@ -61,6 +192,7 @@ module ZTK::DSL
61
192
  "#<#{self.class.to_s} id=#{self.id.inspect} #{details.join(', ')}>"
62
193
  end
63
194
 
195
+ # @author Zachary Patten <zachary@jovelabs.net>
64
196
  module ClassMethods
65
197
 
66
198
  def inspect