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

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.
@@ -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