epitools 0.5.103 → 0.5.105
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.
- checksums.yaml +4 -4
- data/README.rdoc +1 -1
- data/Rakefile +2 -2
- data/TODO +1 -1
- data/VERSION +1 -1
- data/lib/epitools.rb +1 -1
- data/lib/epitools/colored.rb +25 -25
- data/lib/epitools/core_ext/enumerable.rb +1 -1
- data/lib/epitools/core_ext/file.rb +6 -2
- data/lib/epitools/core_ext/hash.rb +43 -29
- data/lib/epitools/core_ext/misc.rb +21 -1
- data/lib/epitools/core_ext/object.rb +19 -19
- data/lib/epitools/core_ext/truthiness.rb +5 -5
- data/lib/epitools/daemonize.rb +1 -1
- data/lib/epitools/hexdump.rb +1 -1
- data/lib/epitools/iter.rb +26 -26
- data/lib/epitools/lcs.rb +3 -3
- data/lib/epitools/mimemagic.rb +7 -7
- data/lib/epitools/niceprint.rb +18 -18
- data/lib/epitools/numwords.rb +34 -34
- data/lib/epitools/path.rb +7 -0
- data/lib/epitools/permutations.rb +9 -9
- data/lib/epitools/pretty_backtrace.rb +11 -11
- data/lib/epitools/progressbar.rb +7 -7
- data/lib/epitools/rails.rb +2 -2
- data/lib/epitools/rash.rb +16 -16
- data/lib/epitools/ratio.rb +1 -1
- data/lib/epitools/sys.rb +47 -47
- data/lib/epitools/trie.rb +4 -4
- data/lib/epitools/typed_struct.rb +5 -5
- data/lib/epitools/wm.rb +6 -6
- data/lib/epitools/zopen.rb +2 -2
- data/spec/autoreq_spec.rb +5 -5
- data/spec/browser_spec.rb +1 -1
- data/spec/colored_spec.rb +5 -5
- data/spec/core_ext_spec.rb +1 -1
- data/spec/histogram_spec.rb +3 -3
- data/spec/iter_spec.rb +16 -16
- data/spec/lcs_spec.rb +5 -5
- data/spec/numwords_spec.rb +8 -8
- data/spec/permutations_spec.rb +9 -9
- data/spec/rash_spec.rb +7 -7
- data/spec/ratio_spec.rb +5 -5
- data/spec/sys_spec.rb +6 -6
- data/spec/term_spec.rb +7 -7
- data/spec/typed_struct_spec.rb +5 -5
- data/spec/wm_spec.rb +4 -4
- data/spec/zopen_spec.rb +11 -11
- metadata +2 -2
data/lib/epitools/rash.rb
CHANGED
@@ -8,9 +8,9 @@
|
|
8
8
|
# greeting["Mrs. Steve Austin"] #=> "Evening, madame."
|
9
9
|
#
|
10
10
|
class Rash
|
11
|
-
|
11
|
+
|
12
12
|
attr_accessor :optimize_every
|
13
|
-
|
13
|
+
|
14
14
|
def initialize(initial={})
|
15
15
|
@hash = {}
|
16
16
|
@regexes = []
|
@@ -18,7 +18,7 @@ class Rash
|
|
18
18
|
@regex_counts = Hash.new(0)
|
19
19
|
@optimize_every = 500
|
20
20
|
@lookups = 0
|
21
|
-
|
21
|
+
|
22
22
|
update(initial)
|
23
23
|
end
|
24
24
|
|
@@ -28,7 +28,7 @@ class Rash
|
|
28
28
|
end
|
29
29
|
self
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def []=(key, value)
|
33
33
|
case key
|
34
34
|
when Regexp
|
@@ -39,20 +39,20 @@ class Rash
|
|
39
39
|
end
|
40
40
|
@hash[key] = value
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
#
|
44
44
|
# Return the first thing that matches the key.
|
45
45
|
#
|
46
46
|
def [](key)
|
47
47
|
all(key).first
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
#
|
51
51
|
# Return everything that matches the query.
|
52
52
|
#
|
53
53
|
def all(query)
|
54
|
-
return to_enum(:all, query) unless block_given?
|
55
|
-
|
54
|
+
return to_enum(:all, query) unless block_given?
|
55
|
+
|
56
56
|
if @hash.include? query
|
57
57
|
yield @hash[query]
|
58
58
|
return
|
@@ -72,22 +72,22 @@ class Rash
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
when Integer
|
77
|
-
@ranges.each do |range|
|
77
|
+
@ranges.each do |range|
|
78
78
|
yield @hash[range] if range.include? query
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
when Regexp
|
82
82
|
# TODO: this doesn't seem very useful. should I ditch it? let me know!
|
83
83
|
@hash.each do |key,val|
|
84
|
-
yield val if key.is_a? String and query =~ key
|
84
|
+
yield val if key.is_a? String and query =~ key
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def method_missing(*args, &block)
|
92
92
|
@hash.send(*args, &block)
|
93
93
|
end
|
@@ -95,7 +95,7 @@ class Rash
|
|
95
95
|
private
|
96
96
|
|
97
97
|
def optimize_if_necessary!
|
98
|
-
if (@lookups += 1) >= @optimize_every
|
98
|
+
if (@lookups += 1) >= @optimize_every
|
99
99
|
@regexes = @regex_counts.sort_by { |regex,count| -count }.map { |regex,count| regex }
|
100
100
|
@lookups = 0
|
101
101
|
end
|
data/lib/epitools/ratio.rb
CHANGED
data/lib/epitools/sys.rb
CHANGED
@@ -5,11 +5,11 @@ require 'epitools/minimal'
|
|
5
5
|
# Includes: process listing, platform detection, etc.
|
6
6
|
#
|
7
7
|
module Sys
|
8
|
-
|
8
|
+
|
9
9
|
#-----------------------------------------------------------------------------
|
10
10
|
|
11
11
|
#
|
12
|
-
# Return the current operating system: Darwin, Linux, or Windows.
|
12
|
+
# Return the current operating system: Darwin, Linux, or Windows.
|
13
13
|
#
|
14
14
|
def self.os
|
15
15
|
return @os if @os
|
@@ -20,7 +20,7 @@ module Sys
|
|
20
20
|
else
|
21
21
|
host_os = Config::CONFIG['host_os']
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
case host_os
|
25
25
|
when /darwin/
|
26
26
|
@os = "Darwin"
|
@@ -36,7 +36,7 @@ module Sys
|
|
36
36
|
|
37
37
|
@os
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
#
|
41
41
|
# Is this Linux?
|
42
42
|
#
|
@@ -85,10 +85,10 @@ module Sys
|
|
85
85
|
[:minflt, :to_i],
|
86
86
|
[:command,:to_s],
|
87
87
|
]
|
88
|
-
|
88
|
+
|
89
89
|
PS_FIELDS = PS_FIELD_TABLE.map { |name, func| name }
|
90
90
|
PS_FIELD_TRANSFORMS = Hash[ *PS_FIELD_TABLE.flatten ]
|
91
|
-
|
91
|
+
|
92
92
|
class ProcessNotFound < Exception; end
|
93
93
|
|
94
94
|
#
|
@@ -124,7 +124,7 @@ module Sys
|
|
124
124
|
"U"=>:wait,
|
125
125
|
"Z"=>:zombie,
|
126
126
|
"W"=>:swapped,
|
127
|
-
|
127
|
+
|
128
128
|
"s"=>:session_leader,
|
129
129
|
"X"=>:debugging,
|
130
130
|
"E"=>:exiting,
|
@@ -133,7 +133,7 @@ module Sys
|
|
133
133
|
"+"=>:foreground,
|
134
134
|
"L"=>:locked_pages,
|
135
135
|
}
|
136
|
-
|
136
|
+
|
137
137
|
LINUX_STATES = {
|
138
138
|
"R"=>:running,
|
139
139
|
"S"=>:sleeping,
|
@@ -150,7 +150,7 @@ module Sys
|
|
150
150
|
"L"=>:locked_pages,
|
151
151
|
"l"=>:multithreaded,
|
152
152
|
}
|
153
|
-
|
153
|
+
|
154
154
|
def initialize(*args)
|
155
155
|
@dead = false
|
156
156
|
args << stat_to_state(args[PS_FIELDS.index(:stat)])
|
@@ -168,11 +168,11 @@ module Sys
|
|
168
168
|
|
169
169
|
#
|
170
170
|
# Convert all the process information to a hash.
|
171
|
-
#
|
171
|
+
#
|
172
172
|
def to_hash
|
173
173
|
Hash[ *members.zip(values).flatten(1) ]
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
#
|
177
177
|
# Send the TERM signal to this process.
|
178
178
|
#
|
@@ -181,61 +181,61 @@ module Sys
|
|
181
181
|
Process.kill(signal, pid)
|
182
182
|
# TODO: handle exception Errno::ESRCH (no such process)
|
183
183
|
end
|
184
|
-
|
184
|
+
|
185
185
|
#
|
186
186
|
# Has this process been killed?
|
187
187
|
#
|
188
188
|
def dead?
|
189
189
|
@dead ||= Sys.pid(pid).empty?
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
#
|
193
193
|
# Refresh this process' statistics.
|
194
194
|
#
|
195
195
|
def refresh
|
196
196
|
processes = Sys.ps(pid)
|
197
|
-
|
197
|
+
|
198
198
|
if processes.empty?
|
199
199
|
@dead = true
|
200
200
|
raise ProcessNotFound
|
201
201
|
end
|
202
|
-
|
202
|
+
|
203
203
|
updated_process = processes.first
|
204
204
|
members.each { |member| self[member] = updated_process[member] }
|
205
205
|
self
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
alias_method :name, :command
|
209
209
|
|
210
|
-
# Linux-specific methods
|
210
|
+
# Linux-specific methods
|
211
211
|
if Sys.linux?
|
212
|
-
|
212
|
+
|
213
213
|
def exename
|
214
214
|
@exename ||= File.readlink("/proc/#{pid}/exe") rescue :unknown
|
215
215
|
@exename == :unknown ? nil : @exename
|
216
216
|
end
|
217
|
-
|
217
|
+
|
218
218
|
def fds
|
219
219
|
Dir["/proc/#{pid}/fd/*"].map { |fd| File.readlink(fd) rescue nil }
|
220
220
|
end
|
221
|
-
|
221
|
+
|
222
222
|
end
|
223
|
-
|
224
|
-
private
|
225
|
-
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
226
|
def stat_to_state(str)
|
227
227
|
states = case Sys.os
|
228
228
|
when "Linux" then LINUX_STATES
|
229
229
|
when "Darwin" then DARWIN_STATES
|
230
230
|
else raise "Unsupported platform: #{Sys.os}"
|
231
231
|
end
|
232
|
-
|
232
|
+
|
233
233
|
str.scan(/./).map { |char| states[char] }.compact
|
234
234
|
end
|
235
235
|
end
|
236
236
|
|
237
237
|
#-----------------------------------------------------------------------------
|
238
|
-
|
238
|
+
|
239
239
|
def self.tree
|
240
240
|
tree = Sys.ps.group_by(&:ppid)
|
241
241
|
Hash[tree.map do |ppid, children|
|
@@ -246,35 +246,35 @@ module Sys
|
|
246
246
|
|
247
247
|
#
|
248
248
|
# List all (or specified) processes, and return ProcessInfo objects.
|
249
|
-
# (Takes an optional list of pids as arguments.)
|
249
|
+
# (Takes an optional list of pids as arguments.)
|
250
250
|
#
|
251
251
|
def self.ps(*pids)
|
252
252
|
#return @@cache if @@cache
|
253
253
|
|
254
254
|
options = PS_FIELDS.join(',')
|
255
|
-
|
255
|
+
|
256
256
|
pids = pids.map(&:to_i)
|
257
|
-
|
257
|
+
|
258
258
|
if pids.any?
|
259
259
|
command = "ps -p #{pids.join(',')} -o #{options}"
|
260
260
|
else
|
261
261
|
command = "ps awx -o #{options}"
|
262
262
|
end
|
263
263
|
|
264
|
-
lines = `#{command}`.lines.to_a
|
264
|
+
lines = `#{command}`.lines.to_a
|
265
265
|
|
266
266
|
lines[1..-1].map do |line|
|
267
267
|
fields = line.split
|
268
268
|
if fields.size > PS_FIELDS.size
|
269
|
-
fields = fields[0..PS_FIELDS.size-2] + [fields[PS_FIELDS.size-1..-1].join(" ")]
|
269
|
+
fields = fields[0..PS_FIELDS.size-2] + [fields[PS_FIELDS.size-1..-1].join(" ")]
|
270
270
|
end
|
271
|
-
|
271
|
+
|
272
272
|
fields = PS_FIELDS.zip(fields).map { |name, value| value.send(PS_FIELD_TRANSFORMS[name]) }
|
273
|
-
|
273
|
+
|
274
274
|
ProcessInfo.new(*fields)
|
275
275
|
end
|
276
276
|
end
|
277
|
-
|
277
|
+
|
278
278
|
#-----------------------------------------------------------------------------
|
279
279
|
|
280
280
|
def self.refresh
|
@@ -288,7 +288,7 @@ module Sys
|
|
288
288
|
# (Execute Signal.list to see what's available.)
|
289
289
|
#
|
290
290
|
# No paramters defaults to all signals except VTALRM, CHLD, CLD, and EXIT.
|
291
|
-
#
|
291
|
+
#
|
292
292
|
def self.trap(*args, &block)
|
293
293
|
options = if args.last.is_a?(Hash) then args.pop else Hash.new end
|
294
294
|
args = [args].flatten
|
@@ -304,14 +304,14 @@ module Sys
|
|
304
304
|
Signal.trap(signal) { yield signal }
|
305
305
|
end
|
306
306
|
end
|
307
|
-
|
307
|
+
|
308
308
|
#-----------------------------------------------------------------------------
|
309
309
|
|
310
310
|
#
|
311
311
|
# A metaprogramming helper that allows you to write platform-specific methods
|
312
312
|
# which the user can call with one name. Here's how to use it:
|
313
313
|
#
|
314
|
-
# Define these methods:
|
314
|
+
# Define these methods:
|
315
315
|
# reboot_linux, reboot_darwin, reboot_windows
|
316
316
|
#
|
317
317
|
# Call the magic method:
|
@@ -321,7 +321,7 @@ module Sys
|
|
321
321
|
#
|
322
322
|
# (Note: If you didn't create a method for a specific platform, then you'll get
|
323
323
|
# NoMethodError exception when the "reboot" method is called on that platform.)
|
324
|
-
#
|
324
|
+
#
|
325
325
|
def self.cross_platform_method(name)
|
326
326
|
platform_method_name = "#{name}_#{os.downcase}"
|
327
327
|
metaclass.instance_eval do
|
@@ -342,11 +342,11 @@ module Sys
|
|
342
342
|
def self.hostname_linux
|
343
343
|
`uname -n`.strip
|
344
344
|
end
|
345
|
-
|
345
|
+
|
346
346
|
def self.hostname_mac
|
347
347
|
`uname -n`.strip.gsub(/\.local$/, '')
|
348
348
|
end
|
349
|
-
|
349
|
+
|
350
350
|
def self.hostname_windows
|
351
351
|
raise NotImplementedError
|
352
352
|
end
|
@@ -394,7 +394,7 @@ module Sys
|
|
394
394
|
|
395
395
|
device_ips
|
396
396
|
end
|
397
|
-
|
397
|
+
|
398
398
|
#
|
399
399
|
# Windows: Return a hash of (device name, IP address) pairs.
|
400
400
|
#
|
@@ -411,7 +411,7 @@ module Sys
|
|
411
411
|
end
|
412
412
|
result
|
413
413
|
end
|
414
|
-
|
414
|
+
|
415
415
|
#-----------------------------------------------------------------------------
|
416
416
|
|
417
417
|
cross_platform_method :browser_open
|
@@ -440,11 +440,11 @@ module Sys
|
|
440
440
|
#Mem: 4124380 3388548 735832 0 561888 968004
|
441
441
|
#-/+ buffers/cache: 1858656 2265724
|
442
442
|
#Swap: 2104504 166724 1937780
|
443
|
-
|
443
|
+
|
444
444
|
#$ vmstat
|
445
|
-
raise "Not implemented"
|
445
|
+
raise "Not implemented"
|
446
446
|
end
|
447
|
-
|
447
|
+
|
448
448
|
def self.memstat_darwin
|
449
449
|
#$ vm_stat
|
450
450
|
#Mach Virtual Memory Statistics: (page size of 4096 bytes)
|
@@ -462,7 +462,7 @@ module Sys
|
|
462
462
|
#Object cache: 16 hits of 255782 lookups (0% hit rate)
|
463
463
|
|
464
464
|
#$ iostat
|
465
|
-
raise "Not implemented"
|
465
|
+
raise "Not implemented"
|
466
466
|
end
|
467
467
|
|
468
468
|
#-----------------------------------------------------------------------------
|
@@ -477,10 +477,10 @@ module Sys
|
|
477
477
|
#SMC DRIVE BAY 1: 41 C
|
478
478
|
#SMC NORTHBRIDGE POS 1: 46 C
|
479
479
|
#SMC WLAN CARD: 45 C
|
480
|
-
raise "Not implemented"
|
480
|
+
raise "Not implemented"
|
481
481
|
end
|
482
482
|
|
483
|
-
end
|
483
|
+
end
|
484
484
|
|
485
485
|
if $0 == __FILE__
|
486
486
|
require 'pp'
|
data/lib/epitools/trie.rb
CHANGED
@@ -80,11 +80,11 @@
|
|
80
80
|
# ''
|
81
81
|
# /
|
82
82
|
# r
|
83
|
-
# / \
|
83
|
+
# / \
|
84
84
|
# o u
|
85
|
-
# / \
|
85
|
+
# / \
|
86
86
|
# w b
|
87
|
-
# \
|
87
|
+
# \
|
88
88
|
# y
|
89
89
|
#
|
90
90
|
# are actually stored as
|
@@ -92,7 +92,7 @@
|
|
92
92
|
# ''
|
93
93
|
# /
|
94
94
|
# r
|
95
|
-
# / \
|
95
|
+
# / \
|
96
96
|
# ow uby
|
97
97
|
#
|
98
98
|
# Because of this implementation (and to allow Trie.find to be called on
|
@@ -21,11 +21,11 @@
|
|
21
21
|
# ["bigdecimal"] => BigDecimal
|
22
22
|
# ["hex"] => Integer
|
23
23
|
# ["date", "time", "datetime"] => DateTime (using DateTime.parse)
|
24
|
-
# ["timestamp", "unixtime"] => Time (using Time.at)
|
24
|
+
# ["timestamp", "unixtime"] => Time (using Time.at)
|
25
25
|
# ["bool", "boolean"] => Boolean, using the following rules:
|
26
|
-
# false when: false, nil, 0, "0", "off", "no",
|
26
|
+
# false when: false, nil, 0, "0", "off", "no",
|
27
27
|
# "false", "disabled", "disable"
|
28
|
-
# true when: true, 1, "1", "on", "yes",
|
28
|
+
# true when: true, 1, "1", "on", "yes",
|
29
29
|
# "true", "enabled", "enable"
|
30
30
|
#
|
31
31
|
class TypedStruct < Struct
|
@@ -48,7 +48,7 @@ class TypedStruct < Struct
|
|
48
48
|
["hex"] => proc { |me| me.to_i(16) },
|
49
49
|
["date", "time", "datetime"] => proc { |me| DateTime.parse me },
|
50
50
|
["timestamp", "unixtime"] => proc { |me| Time.at me },
|
51
|
-
["bool", "boolean"] => proc do |me|
|
51
|
+
["bool", "boolean"] => proc do |me|
|
52
52
|
case me
|
53
53
|
when false, nil, 0, /^(0|off|no|false|disabled?)$/
|
54
54
|
false
|
@@ -93,7 +93,7 @@ class TypedStruct < Struct
|
|
93
93
|
struct = new(*pairs.transpose.first)
|
94
94
|
|
95
95
|
# overload setter methods to call the proc
|
96
|
-
pairs.each do |field, converter|
|
96
|
+
pairs.each do |field, converter|
|
97
97
|
next if converter == :passthru
|
98
98
|
struct.send(:define_method, "#{field}=") do |val|
|
99
99
|
self[field] = ( val and converter.call val )
|