reel-eye 0.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1cef15d8559f95d22d04f0b423ee81bcd9b10ef2
4
- data.tar.gz: c5f01498bb84e011b02d05fc2146ea880a7524ae
3
+ metadata.gz: a4e0a9547f32b0eae31d793656a43b559eaa2df7
4
+ data.tar.gz: a2a6fa219d1b8d4f904075013ba61466cc32a881
5
5
  SHA512:
6
- metadata.gz: ae2991e43e2413b5897ce17bf72fcd10bbfb651b83501709134efff06c1120ee38eac8df2bdebc0c1ba9a6cccf1cd60f866e931d369bedd2853fd30ddcacc38c
7
- data.tar.gz: 6ecfa8784c8363d7c62f694dd4f157c23f29a3bbb5274c3055e4b0847e5d4512746fafc342d726e59ff42731783bf3911734c8de2cbf872aa98daafebbe505b4
6
+ metadata.gz: 8b252fa537587c2678c9b3f85af63bbb2796ac1bac895c6ff8a1954847612f4c2cf4968fb72664439a584bcbef6701f1a7f8ed26b4cc631c2f4b48da44ca74aa
7
+ data.tar.gz: 737744391f0de8816aef5728d52f05649b48bb377c8b5c89808d98b3a2dc06f52cbf3296efdd2834a508f572efc8e247de8ac639ed74adb4812d1f82b7b43610
@@ -2,7 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - "1.9.2"
4
4
  - "1.9.3"
5
- - "2.0"
5
+ - "2.0.0"
6
+ - "2.1.0"
6
7
  script: bundle exec rake N=15
7
8
  #before_script:
8
9
  # - bundle exec rake remove_coverage
data/CHANGES.md CHANGED
@@ -1,10 +1,16 @@
1
+ 0.5.1
2
+ -----
3
+ * fix ordering in info (#27)
4
+ * add log rotation (#26)
5
+ * minor load fixes
6
+
1
7
  0.5
2
8
  -------
3
9
  * little fixes in dsl
4
10
  * remove activesupport dependency
5
11
  * rename `state` trigger to `transition`
6
12
  * add runtime, cputime, file_touched checks
7
- * real cpu check
13
+ * real cpu check (#9)
8
14
  * use sigar gem instead of `ps ax`
9
15
  * refactor cli (requires `eye q && eye l` after update gem from 0.4.x)
10
16
  * update celluloid to 0.15
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2013 'Konstantin Makarchev'
1
+ Copyright (c) 2012-2014 'Konstantin Makarchev'
2
2
 
3
3
  MIT License
4
4
 
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -53,6 +53,7 @@ Eye::Control.set_proc_line
53
53
  server.async.run
54
54
 
55
55
  trap("INT"){ exit }
56
+ trap("USR1"){ Eye::Logger.reopen }
56
57
  trap("USR2"){ GC.start }
57
58
 
58
59
  sleep
@@ -40,5 +40,6 @@ Gem::Specification.new do |gem|
40
40
  gem.add_development_dependency 'thin'
41
41
  gem.add_development_dependency 'xmpp4r'
42
42
  gem.add_development_dependency 'coveralls'
43
+ gem.add_development_dependency 'simplecov', '>= 0.8.1'
43
44
  gem.add_development_dependency 'parallel_tests'
44
45
  end
data/lib/eye.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Eye
2
- VERSION = "0.5"
3
- ABOUT = "ReelEye v#{VERSION} (c) 2012-2013 @kostya"
2
+ VERSION = "0.5.1"
3
+ ABOUT = "ReelEye v#{VERSION} (c) 2012-2014 @kostya"
4
4
  PROCLINE = "reel-eye monitoring v#{VERSION}"
5
5
 
6
6
  autoload :Process, 'eye/process'
@@ -23,7 +23,7 @@ class Eye::Application
23
23
 
24
24
  # sort processes in name order
25
25
  def resort_groups
26
- @groups = @groups.sort_by{|gr| gr.name == '__default__' ? 'zzzzz' : gr.name }
26
+ @groups = @groups.sort { |a, b| a.hidden ? 1 : (b.hidden ? -1 : (a.name <=> b.name)) }
27
27
  end
28
28
 
29
29
  def status_data(debug = false)
@@ -32,8 +32,8 @@ class Eye::Cli < Thor
32
32
  end
33
33
 
34
34
  desc "oinfo", "onelined info"
35
- def oinfo
36
- res = cmd(:short_data)
35
+ def oinfo(mask = nil)
36
+ res = cmd(:short_data, *Array(mask))
37
37
  say render_info(res)
38
38
  say
39
39
  end
@@ -45,7 +45,7 @@ class Eye::Cli < Thor
45
45
  say
46
46
  end
47
47
 
48
- desc "load [CONF, ...]", "load config (start eye-daemon if not) (-f foreground start)"
48
+ desc "load [CONF, ...]", "load config (run eye-daemon if not) (-f foreground load)"
49
49
  method_option :foreground, :type => :boolean, :aliases => "-f"
50
50
  def load(*configs)
51
51
  configs.map!{ |c| File.expand_path(c) } if !configs.empty?
@@ -111,7 +111,7 @@ class Eye::Cli < Thor
111
111
  def check(conf)
112
112
  conf = File.expand_path(conf) if conf && !conf.empty?
113
113
 
114
- Eye::System.host = options[:host] if options[:host]
114
+ Eye::Local.host = options[:host] if options[:host]
115
115
  Eye::Dsl.verbose = options[:verbose]
116
116
 
117
117
  say_load_result Eye::Controller.new.check(conf), :syntax => true
@@ -123,7 +123,7 @@ class Eye::Cli < Thor
123
123
  def explain(conf)
124
124
  conf = File.expand_path(conf) if conf && !conf.empty?
125
125
 
126
- Eye::System.host = options[:host] if options[:host]
126
+ Eye::Local.host = options[:host] if options[:host]
127
127
  Eye::Dsl.verbose = options[:verbose]
128
128
 
129
129
  say_load_result Eye::Controller.new.explain(conf), :print_config => true, :syntax => true
@@ -131,6 +131,8 @@ class Eye::Cli < Thor
131
131
 
132
132
  desc "watch [MASK]", "interactive processes info"
133
133
  def watch(*args)
134
+ error!("You should install watch utility") if `which watch`.empty?
135
+
134
136
  cmd = if `watch --version 2>&1`.chop > '0.2.0'
135
137
  "watch -n 1 --color #{$0} i #{args * ' '}"
136
138
  else
@@ -68,7 +68,7 @@ private
68
68
  if res == []
69
69
  error! "command :#{_cmd}, objects not found!"
70
70
  else
71
- say "command :#{_cmd} sended to [#{res * ", "}]"
71
+ say "command :#{_cmd} sent to [#{res * ", "}]"
72
72
  end
73
73
  end
74
74
  else
@@ -1,7 +1,5 @@
1
1
  module Eye::Cli::Render
2
2
  private
3
- DF = '%d %b %H:%M'
4
-
5
3
  def render_info(data)
6
4
  error!("unexpected server answer #{data.inspect}") unless data.is_a?(Hash)
7
5
 
@@ -26,7 +24,7 @@ private
26
24
  is_text = data[:state] || data[:states]
27
25
 
28
26
  name = (data[:type] == :application && !is_text) ? "\033[1m#{data[:name]}\033[0m" : data[:name].to_s
29
- off_len = short_state ? 20 : 35
27
+ off_len = 35
30
28
  str = off_str + (name + ' ').ljust(off_len - off, is_text ? '.' : ' ')
31
29
 
32
30
  if short_state
@@ -34,7 +32,7 @@ private
34
32
  elsif data[:state]
35
33
  str += ' ' + data[:state].to_s
36
34
  str += ' (' + resources_str(data[:resources]) + ')' if data[:resources] && data[:state].to_sym == :up
37
- str += " (#{data[:state_reason]} at #{data[:state_changed_at].strftime(DF)})" if data[:state_reason] && data[:state] == 'unmonitored'
35
+ str += " (#{data[:state_reason]} at #{Eye::Utils.human_time2(data[:state_changed_at])})" if data[:state_reason] && data[:state] == 'unmonitored'
38
36
  elsif data[:current_command]
39
37
  chain_progress = if data[:chain_progress]
40
38
  " #{data[:chain_progress][0]} of #{data[:chain_progress][1]}" rescue ''
@@ -60,11 +58,7 @@ private
60
58
  memory, cpu, start_time, pid = r[:memory], r[:cpu], r[:start_time], r[:pid]
61
59
  return '' unless memory && cpu && start_time
62
60
 
63
- res = "#{Eye::Utils.human_time(start_time)}, #{cpu.to_i}%"
64
- res += ", #{memory / 1024 / 1024}Mb"
65
- res += ", <#{pid}>"
66
-
67
- res
61
+ "#{Eye::Utils.human_time(start_time)}, #{cpu.to_i}%, #{memory / 1024 / 1024}Mb, <#{pid}>"
68
62
  end
69
63
 
70
64
  def render_debug_info(data)
@@ -72,28 +66,26 @@ private
72
66
 
73
67
  s = ""
74
68
 
75
- config_yaml = data.delete(:config_yaml)
69
+ if config_yaml = data.delete(:config_yaml)
70
+ s << config_yaml
76
71
 
77
- data.each do |k, v|
78
- s << "#{"#{k}:".ljust(10)} "
72
+ else
73
+ data.each do |k, v|
74
+ s << "#{"#{k}:".ljust(10)} "
75
+
76
+ case k
77
+ when :resources
78
+ s << resources_str(v)
79
+ else
80
+ s << "#{v}"
81
+ end
79
82
 
80
- case k
81
- when :resources
82
- s << resources_str(v)
83
- else
84
- s << "#{v}"
83
+ s << "\n"
85
84
  end
86
85
 
87
86
  s << "\n"
88
87
  end
89
88
 
90
- s << "\n"
91
-
92
- if config_yaml
93
- s << "Current config:\n"
94
- s << config_yaml
95
- end
96
-
97
89
  s
98
90
  end
99
91
 
@@ -117,7 +109,7 @@ private
117
109
  history.chunk{|h| [h[:state], h[:reason].to_s] }.each do |_, hist|
118
110
  if hist.size >= 3
119
111
  res << detail_process_info_string(hist[0])
120
- res << detail_process_info_string(:state => "... #{hist.size - 2} times", :reason => '...', :at => hist[-1][:at])
112
+ res << detail_process_info_string(:state => "... #{hist.size - 2} times", :reason => '...')
121
113
  res << detail_process_info_string(hist[-1])
122
114
  else
123
115
  hist.each do |h|
@@ -131,7 +123,8 @@ private
131
123
 
132
124
  def detail_process_info_string(h)
133
125
  state = h[:state].to_s.ljust(14)
134
- "#{Time.at(h[:at]).strftime(DF)} - #{state} (#{h[:reason]})\n"
126
+ at = h[:at] ? Eye::Utils.human_time2(h[:at]) : '.' * 12
127
+ "#{at} - #{state} (#{h[:reason]})\n"
135
128
  end
136
129
 
137
130
  end
@@ -125,13 +125,13 @@ private
125
125
  @old_groups = {}
126
126
  @old_processes = {}
127
127
 
128
- app = @applications.detect{|c| c.name == app_name}
128
+ app = @applications.detect { |c| c.name == app_name }
129
129
 
130
130
  if app
131
131
  app.groups.each do |group|
132
132
  @old_groups[group.name] = group
133
133
  group.processes.each do |proc|
134
- @old_processes[proc.name] = proc
134
+ @old_processes[group.name + ":" + proc.name] = proc
135
135
  end
136
136
  end
137
137
 
@@ -204,13 +204,17 @@ private
204
204
  end
205
205
 
206
206
  def update_or_create_process(process_name, process_cfg)
207
- if @old_processes[process_name]
208
- debug "update process #{process_name}"
209
- process = @old_processes.delete(process_name)
207
+ postfix = ":" + process_name
208
+ name = process_cfg[:group] + postfix
209
+ key = @old_processes[name] ? name : @old_processes.keys.detect { |n| n.end_with?(postfix) }
210
+
211
+ if @old_processes[key]
212
+ debug "update process #{name}"
213
+ process = @old_processes.delete(key)
210
214
  process.schedule :update_config, process_cfg, Eye::Reason::User.new(:'load config')
211
215
  process
212
216
  else
213
- debug "create process #{process_name}"
217
+ debug "create process #{name}"
214
218
  process = Eye::Process.new(process_cfg)
215
219
  @added_processes << process
216
220
  process
@@ -1,13 +1,9 @@
1
1
  module Eye::Controller::Options
2
2
 
3
- def set_opt_logger(logger)
3
+ def set_opt_logger(logger_args)
4
4
  # do not apply logger, if in stdout state
5
5
  if !%w{stdout stderr}.include?(Eye::Logger.dev)
6
- if logger.blank?
7
- Eye::Logger.link_logger(nil)
8
- else
9
- Eye::Logger.link_logger(logger)
10
- end
6
+ Eye::Logger.link_logger(*logger_args)
11
7
  end
12
8
  end
13
9
 
@@ -10,8 +10,9 @@ module Eye::Controller::Status
10
10
  :ruby => RUBY_DESCRIPTION,
11
11
  :http => @http ? "#{@http.host}:#{@http.port}" : '-',
12
12
  :gems => %w|Celluloid Celluloid::IO StateMachine NIO Sigar|.map{|c| gem_version(c) },
13
- :logger => Eye::Logger.dev,
13
+ :logger => Eye::Logger.args.present? ? [Eye::Logger.dev, *Eye::Logger.args] : Eye::Logger.dev,
14
14
  :pid_path => Eye::Local::pid_path,
15
+ :sock_path => Eye::Local::socket_path,
15
16
  :actors => actors
16
17
  }
17
18
 
@@ -25,7 +26,7 @@ module Eye::Controller::Status
25
26
  end
26
27
 
27
28
  def short_data(*args)
28
- {:subtree => @applications.map{|a| a.status_data_short } }
29
+ {:subtree => info_objects(*args).select{ |o| o.class == Eye::Application }.map{|a| a.status_data_short } }
29
30
  end
30
31
 
31
32
  def history_data(*args)
@@ -41,6 +41,10 @@ class Eye::Dsl
41
41
  def parse_apps(*args)
42
42
  parse(*args).applications
43
43
  end
44
+
45
+ def check_name(name)
46
+ raise Error, "not allow ':' in name '#{name}'" if name.to_s.include?(':')
47
+ end
44
48
  end
45
49
  end
46
50
 
@@ -11,6 +11,7 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
11
11
  end
12
12
 
13
13
  def group(name, &block)
14
+ Eye::Dsl.check_name(name)
14
15
  Eye::Dsl.debug "=> group #{name}"
15
16
 
16
17
  opts = Eye::Dsl::GroupOpts.new(name, self)
@@ -1,12 +1,18 @@
1
1
  class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
2
2
 
3
- create_options_methods([:logger], String)
4
3
  create_options_methods([:logger_level], Fixnum)
5
4
  create_options_methods([:http], Hash)
6
5
 
7
- def set_logger(logger)
8
- logger.blank? ? super('') : super
6
+ def logger(*args)
7
+ if args.empty?
8
+ @config[:logger]
9
+ else
10
+ str = args[0]
11
+ raise Eye::Dsl::Error, "logger should be a String #{str.inspect}" if !(str.is_a?(String) || str == nil)
12
+ @config[:logger] = args
13
+ end
9
14
  end
15
+ alias logger= logger
10
16
 
11
17
  # ==== contact options ==============================
12
18
  def self.add_notify(type)
@@ -11,6 +11,8 @@ class Eye::Dsl::GroupOpts < Eye::Dsl::Opts
11
11
  end
12
12
 
13
13
  def process(name, &block)
14
+ Eye::Dsl.check_name(name)
15
+
14
16
  Eye::Dsl.debug "=> process #{name}"
15
17
 
16
18
  opts = Eye::Dsl::ProcessOpts.new(name, self)
@@ -8,5 +8,5 @@ end
8
8
 
9
9
  # host name
10
10
  def hostname
11
- Eye::System.host
11
+ Eye::Local.host
12
12
  end
@@ -2,6 +2,8 @@ module Eye::Dsl::Main
2
2
  attr_accessor :parsed_config, :parsed_filename
3
3
 
4
4
  def application(name, &block)
5
+ Eye::Dsl.check_name(name)
6
+
5
7
  Eye::Dsl.debug "=> app: #{name}"
6
8
  opts = Eye::Dsl::ApplicationOpts.new(name)
7
9
  opts.instance_eval(&block)
@@ -1,6 +1,6 @@
1
1
  class Eye::Dsl::Opts < Eye::Dsl::PureOpts
2
2
 
3
- STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :start_command,
3
+ STR_OPTIONS = [ :pid_file, :working_dir, :stdout, :stderr, :stdall, :stdin, :start_command,
4
4
  :stop_command, :restart_command, :uid, :gid ]
5
5
  create_options_methods(STR_OPTIONS, String)
6
6
 
@@ -107,6 +107,10 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
107
107
  super
108
108
  end
109
109
 
110
+ def daemonize!
111
+ set_daemonize true
112
+ end
113
+
110
114
  def scoped(&block)
111
115
  h = self.class.new(self.name, self)
112
116
  h.instance_eval(&block)
@@ -139,7 +143,7 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
139
143
  on_server = true
140
144
 
141
145
  if glob.present?
142
- host = Eye::System.host
146
+ host = Eye::Local.host
143
147
 
144
148
  if glob.is_a?(Array)
145
149
  on_server = !!glob.any?{|elem| elem == host}
@@ -24,7 +24,9 @@ module Eye::Local
24
24
  end
25
25
 
26
26
  def home
27
- ENV['EYE_HOME'] || ENV['HOME']
27
+ h = ENV['EYE_HOME'] || ENV['HOME']
28
+ raise "HOME undefined, should be HOME or EYE_HOME environment" unless h
29
+ h
28
30
  end
29
31
 
30
32
  def path(path)
@@ -55,4 +57,15 @@ module Eye::Local
55
57
  RUBY_VERSION >= '2.0'
56
58
  end
57
59
 
60
+ def host
61
+ @host ||= begin
62
+ require 'socket'
63
+ Socket.gethostname
64
+ end
65
+ end
66
+
67
+ def host=(hostname)
68
+ @host = hostname
69
+ end
70
+
58
71
  end
@@ -53,17 +53,18 @@ class Eye::Logger
53
53
  end
54
54
 
55
55
  class << self
56
- attr_reader :dev, :log_level
56
+ attr_reader :dev, :log_level, :args
57
57
 
58
- def link_logger(dev)
58
+ def link_logger(dev, *args)
59
59
  old_dev = @dev
60
60
  @dev = dev ? dev.to_s : nil
61
61
  @dev_fd = @dev
62
+ @args = args
62
63
 
63
64
  @dev_fd = STDOUT if @dev.to_s.downcase == 'stdout'
64
65
  @dev_fd = STDERR if @dev.to_s.downcase == 'stderr'
65
66
 
66
- @inner_logger = InnerLogger.new(@dev_fd)
67
+ @inner_logger = InnerLogger.new(@dev_fd, *args)
67
68
  @inner_logger.level = self.log_level || Logger::INFO
68
69
 
69
70
  rescue Errno::ENOENT, Errno::EACCES
@@ -71,6 +72,10 @@ class Eye::Logger
71
72
  raise
72
73
  end
73
74
 
75
+ def reopen
76
+ link_logger(dev, *args)
77
+ end
78
+
74
79
  def log_level=(level)
75
80
  @log_level = level
76
81
  @inner_logger.level = self.log_level if @inner_logger
@@ -84,7 +84,7 @@ class Eye::Notify
84
84
  end
85
85
 
86
86
  def message_body
87
- "#{message_subject} at #{msg_at.strftime(Eye::Cli::Render::DF)}"
87
+ "#{message_subject} at #{Eye::Utils.human_time2(msg_at)}"
88
88
  end
89
89
 
90
90
  def self.register(base)
@@ -35,7 +35,7 @@ module Eye::Process::Data
35
35
  resources: Eye::SystemResources.resources(pid) }
36
36
 
37
37
  if @states_history
38
- h.merge!( state_changed_at: @states_history.last_state_changed_at,
38
+ h.merge!( state_changed_at: @states_history.last_state_changed_at.to_i,
39
39
  state_reason: @states_history.last_reason )
40
40
  end
41
41
 
@@ -14,7 +14,7 @@ module Eye::Process::Notify
14
14
  # send notifies
15
15
  if self[:notify].present?
16
16
  message = {:message => msg, :name => name,
17
- :full_name => full_name, :pid => pid, :host => Eye::System.host, :level => level,
17
+ :full_name => full_name, :pid => pid, :host => Eye::Local.host, :level => level,
18
18
  :at => Time.now }
19
19
 
20
20
  self[:notify].each do |contact, not_level|
@@ -98,45 +98,13 @@ module Eye::System
98
98
  Process.detach(pid) if pid
99
99
  end
100
100
 
101
- # get table
102
- # {pid => {:rss =>, :cpu =>, :ppid => , :start_time => }}
103
- # slow
104
- def ps_aux
105
- str = Process.send('`', PS_AUX_CMD).force_encoding('binary')
106
- h = {}
107
- str.each_line do |line|
108
- chunk = line.strip.split(/\s+/)
109
- h[chunk[0].to_i] = { :ppid => chunk[1].to_i, :cpu => chunk[2].to_i,
110
- :rss => chunk[3].to_i, :start_time => chunk[4] }
111
- end
112
- h
113
- end
114
-
115
101
  # normalize file
116
102
  def normalized_file(file, working_dir = nil)
117
103
  Pathname.new(file).expand_path(working_dir).to_s
118
104
  end
119
105
 
120
- def host
121
- @host ||= begin
122
- require 'socket'
123
- Socket.gethostname
124
- end
125
- end
126
-
127
- # set host for tests
128
- def host=(hostname)
129
- @host = hostname
130
- end
131
-
132
106
  private
133
107
 
134
- PS_AUX_CMD = if RUBY_PLATFORM.include?('darwin')
135
- 'ps axo pid,ppid,pcpu,rss,start'
136
- else
137
- 'ps axo pid,ppid,pcpu,rss,start_time'
138
- end
139
-
140
108
  def spawn_options(config = {})
141
109
  o = {pgroup: true, chdir: config[:working_dir] || '/'}
142
110
  o.update(out: [config[:stdout], 'a']) if config[:stdout]
@@ -8,11 +8,6 @@ class Eye::Trigger::Flapping < Eye::Trigger
8
8
  param :retry_in, [Float, Fixnum]
9
9
  param :retry_times, [Fixnum]
10
10
 
11
- def initialize(*args)
12
- super
13
- @last_at = nil
14
- end
15
-
16
11
  def check(transition)
17
12
  on_flapping if transition.event == :crashed && !good?
18
13
  end
@@ -23,4 +23,10 @@ module Eye::Utils
23
23
  time.strftime (d1 == d2) ? D1 : D2
24
24
  end
25
25
 
26
+ DF = '%d %b %H:%M'
27
+
28
+ def self.human_time2(unix_time)
29
+ Time.at(unix_time.to_i).strftime(DF)
30
+ end
31
+
26
32
  end
@@ -29,6 +29,10 @@ class Eye::Utils::AliveArray
29
29
  self.class.new super
30
30
  end
31
31
 
32
+ def sort(&block)
33
+ self.class.new super
34
+ end
35
+
32
36
  def +(other)
33
37
  if other.is_a?(Eye::Utils::AliveArray)
34
38
  @arr += other.pure
@@ -1,7 +1,10 @@
1
1
  # http://stackoverflow.com/questions/7263268/ruby-symbolto-proc-leaks-references-in-1-9-2-p180
2
2
 
3
- class Symbol
4
- def to_proc
5
- lambda { |x| x.send(self) }
3
+ unless defined?(SimpleCov) # simplecov somehow crashed with this
4
+
5
+ class Symbol
6
+ def to_proc
7
+ lambda { |x| x.send(self) }
8
+ end
6
9
  end
7
10
  end
@@ -50,6 +50,11 @@ class Array
50
50
  end
51
51
 
52
52
  class Numeric
53
+ def percents
54
+ self
55
+ end
56
+ alias :percent :percents
57
+
53
58
  def seconds
54
59
  self
55
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reel-eye
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Makarchev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-27 00:00:00.000000000 Z
11
+ date: 2014-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: celluloid
@@ -276,6 +276,20 @@ dependencies:
276
276
  - - '>='
277
277
  - !ruby/object:Gem::Version
278
278
  version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: simplecov
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - '>='
284
+ - !ruby/object:Gem::Version
285
+ version: 0.8.1
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - '>='
291
+ - !ruby/object:Gem::Version
292
+ version: 0.8.1
279
293
  - !ruby/object:Gem::Dependency
280
294
  name: parallel_tests
281
295
  requirement: !ruby/object:Gem::Requirement