epitools 0.4.34 → 0.4.35
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.
- data/VERSION +1 -1
- data/epitools.gemspec +2 -2
- data/lib/epitools.rb +7 -2
- data/lib/epitools/basetypes.rb +53 -15
- data/lib/epitools/browser.rb +1 -5
- data/lib/epitools/browser/cache.rb +1 -16
- data/lib/epitools/path.rb +55 -17
- data/lib/epitools/permutations.rb +2 -2
- data/lib/epitools/sys.rb +20 -1
- data/spec/basetypes_spec.rb +5 -3
- data/spec/browser_spec.rb +4 -4
- data/spec/sys_spec.rb +4 -2
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.35
|
data/epitools.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{epitools}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.35"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["epitron"]
|
12
|
-
s.date = %q{2011-05-
|
12
|
+
s.date = %q{2011-05-20}
|
13
13
|
s.description = %q{Miscellaneous utility libraries to make my life easier.}
|
14
14
|
s.email = %q{chris@ill-logic.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/epitools.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
autoload :Path, 'epitools/path'
|
2
|
+
autoload :Browser, 'epitools/browser'
|
3
|
+
autoload :Rash, 'epitools/rash'
|
4
|
+
autoload :Ratio, 'epitools/ratio'
|
5
|
+
autoload :Sys, 'epitools/sys'
|
6
|
+
|
1
7
|
class Object
|
2
8
|
|
3
9
|
unless defined?(__DIR__)
|
@@ -27,8 +33,6 @@ end
|
|
27
33
|
basetypes
|
28
34
|
niceprint
|
29
35
|
string_to_proc
|
30
|
-
ratio
|
31
|
-
path
|
32
36
|
zopen
|
33
37
|
colored
|
34
38
|
clitools
|
@@ -37,3 +41,4 @@ end
|
|
37
41
|
].each do |mod|
|
38
42
|
require_wrapper.call mod
|
39
43
|
end
|
44
|
+
|
data/lib/epitools/basetypes.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
require 'pp'
|
2
2
|
|
3
|
-
|
3
|
+
autoload :URI, 'uri'
|
4
|
+
autoload :CGI, 'cgi'
|
5
|
+
autoload :Base64, 'base64'
|
6
|
+
module Digest
|
7
|
+
autoload :MD5, 'digest/md5'
|
8
|
+
autoload :SHA1, 'digest/sha1'
|
9
|
+
end
|
10
|
+
autoload :JSON, 'json'
|
11
|
+
|
12
|
+
|
13
|
+
## Alias "Enumerator" to "Enum"
|
4
14
|
|
5
15
|
if RUBY_VERSION["1.8"]
|
6
16
|
require 'enumerator'
|
@@ -16,6 +26,7 @@ unless defined? Enum
|
|
16
26
|
end
|
17
27
|
|
18
28
|
class Object
|
29
|
+
|
19
30
|
#
|
20
31
|
# Slightly gross hack to add a class method.
|
21
32
|
#
|
@@ -46,6 +57,8 @@ end
|
|
46
57
|
class Numeric
|
47
58
|
def integer?; true; end
|
48
59
|
|
60
|
+
def truthy?; self > 0; end
|
61
|
+
|
49
62
|
def commatize
|
50
63
|
to_s.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
|
51
64
|
end
|
@@ -88,6 +101,18 @@ class String
|
|
88
101
|
strip.size == 0
|
89
102
|
end
|
90
103
|
|
104
|
+
#
|
105
|
+
# Does this string contain something that means roughly "true"?
|
106
|
+
#
|
107
|
+
def truthy?
|
108
|
+
case strip.downcase
|
109
|
+
when "1", "true", "yes", "on", "enabled", "affirmative"
|
110
|
+
true
|
111
|
+
else
|
112
|
+
false
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
91
116
|
#
|
92
117
|
# Convert \r\n to \n
|
93
118
|
#
|
@@ -113,7 +138,8 @@ class String
|
|
113
138
|
# Like #lines, but skips empty lines and removes \n's.
|
114
139
|
#
|
115
140
|
def nice_lines
|
116
|
-
|
141
|
+
# note: $/ is the platform's newline separator
|
142
|
+
split($/).select{|l| not l.blank? }
|
117
143
|
end
|
118
144
|
|
119
145
|
alias_method :clean_lines, :nice_lines
|
@@ -129,7 +155,6 @@ class String
|
|
129
155
|
# Convert non-URI characters into %XXes.
|
130
156
|
#
|
131
157
|
def urlencode
|
132
|
-
require 'uri' unless defined? URI
|
133
158
|
URI.escape(self)
|
134
159
|
end
|
135
160
|
|
@@ -137,7 +162,6 @@ class String
|
|
137
162
|
# Convert an URI's %XXes into regular characters.
|
138
163
|
#
|
139
164
|
def urldecode
|
140
|
-
require 'uri' unless defined? URI
|
141
165
|
URI.unescape(self)
|
142
166
|
end
|
143
167
|
|
@@ -145,15 +169,20 @@ class String
|
|
145
169
|
# Convert a query string to a hash of params
|
146
170
|
#
|
147
171
|
def to_params
|
148
|
-
|
149
|
-
|
172
|
+
CGI.parse(self).map_values do |v|
|
173
|
+
# CGI.parse wraps every value in an array. Unwrap them!
|
174
|
+
if v.is_a?(Array) and v.size == 1
|
175
|
+
v.first
|
176
|
+
else
|
177
|
+
v
|
178
|
+
end
|
179
|
+
end
|
150
180
|
end
|
151
181
|
|
152
182
|
#
|
153
183
|
# Decode a mime64/base64 encoded string
|
154
184
|
#
|
155
185
|
def decode64
|
156
|
-
require 'base64' unless defined? Base64
|
157
186
|
Base64.decode64 self
|
158
187
|
end
|
159
188
|
|
@@ -161,7 +190,6 @@ class String
|
|
161
190
|
# Encode into a mime64/base64 string
|
162
191
|
#
|
163
192
|
def encode64
|
164
|
-
require 'base64' unless defined? Base64
|
165
193
|
Base64.encode64 self
|
166
194
|
end
|
167
195
|
alias_method :base64, :encode64
|
@@ -170,7 +198,6 @@ class String
|
|
170
198
|
# MD5 the string
|
171
199
|
#
|
172
200
|
def md5
|
173
|
-
require 'digest/md5' unless defined? Digest::MD5
|
174
201
|
Digest::MD5.hexdigest self
|
175
202
|
end
|
176
203
|
|
@@ -178,7 +205,6 @@ class String
|
|
178
205
|
# SHA1 the string
|
179
206
|
#
|
180
207
|
def sha1
|
181
|
-
require 'digest/sha1' unless defined? Digest::SHA1
|
182
208
|
Digest::SHA1.hexdigest self
|
183
209
|
end
|
184
210
|
|
@@ -199,7 +225,6 @@ class String
|
|
199
225
|
# Parse object as JSON
|
200
226
|
#
|
201
227
|
def from_json
|
202
|
-
require 'json' unless defined? JSON
|
203
228
|
JSON.parse self
|
204
229
|
end
|
205
230
|
|
@@ -224,9 +249,9 @@ class Integer
|
|
224
249
|
# Convert the number to an array of bits (least significant digit first, or little-endian).
|
225
250
|
#
|
226
251
|
def to_bits
|
252
|
+
# TODO: Why does thos go into an infinite loop in 1.8.7?
|
227
253
|
("%b" % self).chars.to_a.reverse.map(&:to_i)
|
228
254
|
end
|
229
|
-
|
230
255
|
alias_method :bits, :to_bits
|
231
256
|
|
232
257
|
end
|
@@ -242,7 +267,7 @@ end
|
|
242
267
|
|
243
268
|
klass.class_eval do
|
244
269
|
|
245
|
-
alias_method :bit, :[]
|
270
|
+
alias_method :bit, :"[]"
|
246
271
|
|
247
272
|
#
|
248
273
|
# Extends [] so that Integers can be sliced as if they were arrays.
|
@@ -250,9 +275,9 @@ end
|
|
250
275
|
def [](arg)
|
251
276
|
case arg
|
252
277
|
when Integer
|
253
|
-
bit(arg)
|
278
|
+
self.bit(arg)
|
254
279
|
when Range
|
255
|
-
bits[arg]
|
280
|
+
self.bits[arg]
|
256
281
|
end
|
257
282
|
end
|
258
283
|
|
@@ -828,3 +853,16 @@ class Object
|
|
828
853
|
end
|
829
854
|
|
830
855
|
|
856
|
+
#
|
857
|
+
# Emit a quick debug message (only if $DEBUG is true)
|
858
|
+
#
|
859
|
+
def dmsg(msg)
|
860
|
+
if $DEBUG
|
861
|
+
case msg
|
862
|
+
when String
|
863
|
+
puts msg
|
864
|
+
else
|
865
|
+
puts msg.inspect
|
866
|
+
end
|
867
|
+
end
|
868
|
+
end
|
data/lib/epitools/browser.rb
CHANGED
@@ -1,22 +1,6 @@
|
|
1
1
|
require 'mechanize'
|
2
2
|
require 'sqlite3'
|
3
3
|
|
4
|
-
#
|
5
|
-
# Emit a quick debug message (only if $DEBUG is true)
|
6
|
-
#
|
7
|
-
def dmsg(msg)
|
8
|
-
|
9
|
-
if $DEBUG
|
10
|
-
case msg
|
11
|
-
when String
|
12
|
-
puts msg
|
13
|
-
else
|
14
|
-
puts msg.inspect
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
4
|
class Browser
|
21
5
|
|
22
6
|
#
|
@@ -193,6 +177,7 @@ class Browser
|
|
193
177
|
end
|
194
178
|
|
195
179
|
def delete!
|
180
|
+
db.close
|
196
181
|
File.unlink @filename
|
197
182
|
end
|
198
183
|
|
data/lib/epitools/path.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
require 'epitools/basetypes'
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
autoload :FileUtils, 'fileutils'
|
4
|
+
autoload :Tempfile, 'tempfile'
|
5
|
+
autoload :URI, 'uri'
|
6
|
+
module Digest
|
7
|
+
autoload :SHA1, 'digest/sha1'
|
8
|
+
autoload :SHA2, 'digest/sha2'
|
9
|
+
autoload :MD5, 'digest/md5'
|
10
|
+
end
|
11
|
+
|
4
12
|
|
5
13
|
class Path
|
6
14
|
|
@@ -25,20 +33,36 @@ class Path
|
|
25
33
|
end
|
26
34
|
|
27
35
|
def self.tmpfile(prefix="tmp")
|
28
|
-
require 'tempfile' unless defined? Tempfile
|
29
36
|
path = Path[ Tempfile.new(prefix).path ]
|
30
37
|
yield path if block_given?
|
31
38
|
path
|
32
39
|
end
|
33
|
-
|
34
40
|
alias_class_method :tempfile, :tmpfile
|
35
|
-
|
36
41
|
|
37
42
|
def self.home
|
38
43
|
Path[ENV['HOME']]
|
39
44
|
end
|
40
45
|
|
41
|
-
|
46
|
+
def self.pwd
|
47
|
+
File.expand_path Dir.pwd
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.pushd
|
51
|
+
@@dir_stack ||= []
|
52
|
+
@@dir_stack.push pwd
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.popd
|
56
|
+
@@dir_stack ||= [pwd]
|
57
|
+
@@dir_stack.pop
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.cd(dest); Dir.chdir(dest); end
|
61
|
+
|
62
|
+
def self.ls(path); Path[path].ls end
|
63
|
+
|
64
|
+
def self.ls_r(path); Path[path].ls_r; end
|
65
|
+
|
42
66
|
## setters
|
43
67
|
|
44
68
|
attr_writer :base
|
@@ -231,9 +255,10 @@ class Path
|
|
231
255
|
File.read(path, length, offset)
|
232
256
|
end
|
233
257
|
|
234
|
-
def ls
|
235
|
-
|
236
|
-
end
|
258
|
+
def ls; Path[File.join(path, "*")]; end
|
259
|
+
|
260
|
+
def ls_r; Path[File.join(path, "**/*")]; end
|
261
|
+
|
237
262
|
|
238
263
|
## modifying files
|
239
264
|
|
@@ -265,7 +290,11 @@ class Path
|
|
265
290
|
end
|
266
291
|
|
267
292
|
#
|
268
|
-
#
|
293
|
+
# Examples:
|
294
|
+
# Path["SongySong.mp3"].rename(:basename=>"Songy Song")
|
295
|
+
# Path["Songy Song.mp3"].rename(:ext=>"aac")
|
296
|
+
# Path["Songy Song.aac"].rename(:dir=>"/music2")
|
297
|
+
# Path["/music2/Songy Song.aac"].exists? #=> true
|
269
298
|
#
|
270
299
|
def rename(options)
|
271
300
|
raise "Options must be a Hash" unless options.is_a? Hash
|
@@ -276,11 +305,13 @@ class Path
|
|
276
305
|
|
277
306
|
self.path = dest.path # become dest
|
278
307
|
end
|
279
|
-
|
280
|
-
|
281
|
-
|
308
|
+
|
309
|
+
#
|
310
|
+
# Renames the file the specified full path (like Dir.rename.)
|
311
|
+
#
|
312
|
+
def rename_to(path)
|
313
|
+
rename :path=>path
|
282
314
|
end
|
283
|
-
|
284
315
|
alias_method :move, :rename
|
285
316
|
alias_method :ren, :rename
|
286
317
|
|
@@ -288,6 +319,10 @@ class Path
|
|
288
319
|
File.unlink(self)
|
289
320
|
end
|
290
321
|
alias_method :"unlink!", :"delete!"
|
322
|
+
|
323
|
+
def mkdir
|
324
|
+
|
325
|
+
end
|
291
326
|
|
292
327
|
def mkdir_p
|
293
328
|
if exists?
|
@@ -309,21 +344,24 @@ class Path
|
|
309
344
|
end
|
310
345
|
end
|
311
346
|
|
347
|
+
def truncate
|
348
|
+
File.truncate(self)
|
349
|
+
end
|
350
|
+
|
351
|
+
|
352
|
+
|
312
353
|
|
313
354
|
## Checksums
|
314
355
|
|
315
356
|
def sha1
|
316
|
-
require 'digest/sha1' unless defined? Digest::SHA1
|
317
357
|
Digest::SHA1.file(self).hexdigest
|
318
358
|
end
|
319
359
|
|
320
360
|
def sha2
|
321
|
-
require 'digest/sha2' unless defined? Digest::SHA2
|
322
361
|
Digest::SHA2.file(self).hexdigest
|
323
362
|
end
|
324
363
|
|
325
364
|
def md5
|
326
|
-
require 'digest/md5' unless defined? Digest::MD5
|
327
365
|
Digest::MD5.file(self).hexdigest
|
328
366
|
end
|
329
367
|
|
@@ -2,7 +2,7 @@ require 'epitools/basetypes'
|
|
2
2
|
|
3
3
|
class Array
|
4
4
|
|
5
|
-
alias_method :
|
5
|
+
alias_method :mult, :"*"
|
6
6
|
|
7
7
|
#
|
8
8
|
# Overloaded * operator.
|
@@ -23,7 +23,7 @@ class Array
|
|
23
23
|
end
|
24
24
|
result
|
25
25
|
else
|
26
|
-
send(:
|
26
|
+
send(:mult, other)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
data/lib/epitools/sys.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'epitools/basetypes'
|
2
|
+
|
1
3
|
#
|
2
4
|
# Cross-platform operating system functions.
|
3
5
|
# Includes: process listing, platform detection, etc.
|
@@ -322,7 +324,7 @@ module Sys
|
|
322
324
|
# eg: {"eth0"=>"192.168.1.101"}
|
323
325
|
#
|
324
326
|
def self.interfaces_linux
|
325
|
-
sections =
|
327
|
+
sections = `/sbin/ifconfig`.split(/^(?=Link encap:Ethernet)/)
|
326
328
|
sections_with_relevant_ip = sections.select {|i| i =~ /inet/ }
|
327
329
|
|
328
330
|
device_ips = {}
|
@@ -335,6 +337,23 @@ module Sys
|
|
335
337
|
device_ips
|
336
338
|
end
|
337
339
|
|
340
|
+
#
|
341
|
+
# Windows: Return a hash of (device name, IP address) pairs.
|
342
|
+
#
|
343
|
+
def self.interfaces_windows
|
344
|
+
result = {}
|
345
|
+
`ipconfig`.split_before(/^\w.+:/).each do |chunk|
|
346
|
+
chunk.grep(/^Ethernet adapter (.+):\s*$/) do
|
347
|
+
name = $1
|
348
|
+
chunk.grep(/IPv[46] Address[\.\ ]+: (.+)$/) do
|
349
|
+
address = $1.strip
|
350
|
+
result[name] = address
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
result
|
355
|
+
end
|
356
|
+
|
338
357
|
#-----------------------------------------------------------------------------
|
339
358
|
|
340
359
|
cross_platform_method :browser_open
|
data/spec/basetypes_spec.rb
CHANGED
@@ -331,7 +331,9 @@ describe Hash do
|
|
331
331
|
|
332
332
|
it "to_querys" do
|
333
333
|
# this will probably fail half the time in Ruby 1.8 because the hash order is random
|
334
|
-
{
|
334
|
+
params = {"donkeys"=>"7", "stubborn"=>"true"}
|
335
|
+
params.to_query.to_params.should == params
|
336
|
+
params.to_query.in?(["donkeys=7&stubborn=true", "stubborn=true&donkeys=7"]).should == true
|
335
337
|
end
|
336
338
|
|
337
339
|
end
|
@@ -352,13 +354,13 @@ describe "truthiness" do
|
|
352
354
|
{
|
353
355
|
# truthy things
|
354
356
|
true => [
|
355
|
-
"
|
357
|
+
"yes", "on", "1", "Enabled", 1, 1.7, :blah, true, [1,2,3], Enumerator.new([1,2,3], :each),
|
356
358
|
1938389127239847129803741980237498012374,
|
357
359
|
],
|
358
360
|
|
359
361
|
# untruthy things
|
360
362
|
false => [
|
361
|
-
"", " ", 0, 0.0, false, nil, [], Enumerator.new([], :each),
|
363
|
+
"", " ", "asdf", 0, 0.0, false, nil, [], Enumerator.new([], :each),
|
362
364
|
]
|
363
365
|
}.each do |truthiness, objs|
|
364
366
|
objs.each { |obj| obj.truthy?.should == truthiness }
|
data/spec/browser_spec.rb
CHANGED
@@ -51,6 +51,10 @@ describe Browser::Cache do
|
|
51
51
|
@cache = Browser::Cache.new(@agent)
|
52
52
|
end
|
53
53
|
|
54
|
+
after :all do
|
55
|
+
@cache.delete!
|
56
|
+
end
|
57
|
+
|
54
58
|
def new_page(body, url)
|
55
59
|
Mechanize::Page.new(
|
56
60
|
URI.parse(url),
|
@@ -61,10 +65,6 @@ describe Browser::Cache do
|
|
61
65
|
)
|
62
66
|
end
|
63
67
|
|
64
|
-
after :all do
|
65
|
-
@cache.delete!
|
66
|
-
end
|
67
|
-
|
68
68
|
it "writes and reads" do
|
69
69
|
body = "Blah blah blah."
|
70
70
|
url = "http://example.com/url.html"
|
data/spec/sys_spec.rb
CHANGED
@@ -7,10 +7,12 @@ describe Sys::ProcessInfo do
|
|
7
7
|
proc { Sys.linux? }.should_not raise_error
|
8
8
|
proc { Sys.mac? }.should_not raise_error
|
9
9
|
proc { Sys.darwin? }.should_not raise_error
|
10
|
+
proc { Sys.windows? }.should_not raise_error
|
10
11
|
|
11
12
|
%w[Linux Windows Darwin].include?(Sys.os).should == true
|
12
13
|
|
13
|
-
|
14
|
+
truths = [:linux?, :mac?, :windows?].map{|sys| Sys.send(sys)}
|
15
|
+
truths.count(true).should == 1
|
14
16
|
end
|
15
17
|
|
16
18
|
|
@@ -61,7 +63,7 @@ describe Sys::ProcessInfo do
|
|
61
63
|
end
|
62
64
|
|
63
65
|
specify "interfaces" do
|
64
|
-
Sys.interfaces.should_not
|
66
|
+
Sys.interfaces.should_not be_blank
|
65
67
|
end
|
66
68
|
|
67
69
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epitools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 73
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 35
|
10
|
+
version: 0.4.35
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- epitron
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-20 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|