epitools 0.5.129 → 0.5.134
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/VERSION +1 -1
- data/lib/epitools/autoloads.rb +4 -1
- data/lib/epitools/clitools.rb +10 -0
- data/lib/epitools/core_ext/class.rb +5 -19
- data/lib/epitools/core_ext/numbers.rb +27 -8
- data/lib/epitools/core_ext/truthiness.rb +1 -2
- data/lib/epitools/core_ext/uri.rb +29 -15
- data/lib/epitools/gem_ext/oga.rb +31 -0
- data/lib/epitools/job_runner.rb +22 -4
- data/lib/epitools/numwords.rb +1 -1
- data/lib/epitools/path.rb +20 -11
- data/lib/epitools/sys.rb +1 -0
- data/spec/core_ext_spec.rb +20 -29
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2aefbc7936ad578ce3f2ae8806e67be1815f4e2a55ddf43a915bcdaa0ca9f68a
|
4
|
+
data.tar.gz: 6d09789e434d7cda9b66e25ecf1ebf9db61d6236f1342b83743330e42d9ab09f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c98a36281937b7dd6e8f6154af595f5153d51803da0587eafc1a8dec26c96adac899e73c9ef49157b8fadcdf01fb845b60095d9ceb9722b5107c0eeaf6f8550
|
7
|
+
data.tar.gz: ccf09c13ef7df31e8d6994ba1c5550dc606fd61ac909c14f00c53788160a69cb53e7c425156a373732f4fbc7e021bde12c27e850be0ca1cf4735b86d9cf01285
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.134
|
data/lib/epitools/autoloads.rb
CHANGED
@@ -98,8 +98,11 @@ autoreq :Mechanize, 'mechanize'
|
|
98
98
|
autoreq :HTTP, 'http'
|
99
99
|
|
100
100
|
autoreq :Nokogiri, 'nokogiri'
|
101
|
-
autoreq :Oga, 'oga'
|
102
101
|
autoreq :Ox, 'ox'
|
102
|
+
autoreq :Oga do
|
103
|
+
require 'oga'
|
104
|
+
require 'epitools/gem_ext/oga'
|
105
|
+
end
|
103
106
|
|
104
107
|
autoreq :ANSI, 'ansi'
|
105
108
|
|
data/lib/epitools/clitools.rb
CHANGED
@@ -247,3 +247,13 @@ end
|
|
247
247
|
def curl_json(url)
|
248
248
|
JSON.parse(curl(url))
|
249
249
|
end
|
250
|
+
|
251
|
+
def cached_curl(url)
|
252
|
+
cache = "/tmp/curl-#{url.sha1}.cache"
|
253
|
+
if File.exist?(cache)
|
254
|
+
$stderr.puts "cached! => #{cache}"
|
255
|
+
else
|
256
|
+
File.write(cache, curl(url))
|
257
|
+
end
|
258
|
+
File.read(cache)
|
259
|
+
end
|
@@ -1,31 +1,17 @@
|
|
1
1
|
class Class
|
2
2
|
|
3
|
-
#
|
4
|
-
# Return a copy of the class with modules mixed into it.
|
5
|
-
#
|
6
|
-
def self.using(*args)
|
7
|
-
if block_given?
|
8
|
-
yield using(*args)
|
9
|
-
else
|
10
|
-
copy = self.dup
|
11
|
-
args.each { |arg| copy.send(:include, arg) }
|
12
|
-
copy
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
3
|
#
|
18
4
|
# Trace the specified method calls (`meths`, as symbols) to descendends of this class (or all methods if `:*` is supplied).
|
19
5
|
# Output is printed to $stderr.
|
20
6
|
#
|
21
7
|
def trace_messages_to(*meths)
|
22
8
|
return unless $DEBUG
|
23
|
-
|
9
|
+
|
24
10
|
tracers = Module.new
|
25
11
|
parent = self
|
26
12
|
|
27
13
|
$stderr.puts "[*] Tracing messages sent to #{parent} (messages: #{meths.join(", ")})"
|
28
|
-
|
14
|
+
|
29
15
|
meths.each do |meth|
|
30
16
|
case meth
|
31
17
|
when :*
|
@@ -35,9 +21,9 @@ class Class
|
|
35
21
|
end
|
36
22
|
else
|
37
23
|
tracers.define_method(meth) do |*args, &block|
|
38
|
-
|
39
|
-
|
40
|
-
$stderr.puts "[*] #{parent}##{meth}(#{
|
24
|
+
arg_names = args.map(&:inspect)
|
25
|
+
arg_names << "&block" if block
|
26
|
+
$stderr.puts "[*] #{parent}##{meth}(#{arg_names.join(", ")})"
|
41
27
|
if block
|
42
28
|
super(*args, &block)
|
43
29
|
else
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
Number = Numeric # "obj.is_a? Number"
|
2
|
+
Number = Numeric # because "obj.is_a? Number" sounds better!
|
3
3
|
|
4
4
|
class Numeric
|
5
5
|
|
@@ -84,7 +84,8 @@ class Numeric
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
[
|
87
|
+
[
|
88
|
+
:cos,
|
88
89
|
:sin,
|
89
90
|
:tan,
|
90
91
|
:acos,
|
@@ -186,7 +187,8 @@ class Numeric
|
|
186
187
|
end
|
187
188
|
|
188
189
|
BYTE_SIZE_TABLE = {
|
189
|
-
# power
|
190
|
+
# power
|
191
|
+
# of 1024 # units
|
190
192
|
0 => "",
|
191
193
|
1 => "KB",
|
192
194
|
2 => "MB",
|
@@ -213,8 +215,8 @@ class Numeric
|
|
213
215
|
def to_hms
|
214
216
|
seconds = self
|
215
217
|
|
216
|
-
days,
|
217
|
-
hours,
|
218
|
+
days, seconds = seconds.divmod(86400)
|
219
|
+
hours, seconds = seconds.divmod(3600)
|
218
220
|
minutes, seconds = seconds.divmod(60)
|
219
221
|
seconds, frac = seconds.divmod(1)
|
220
222
|
|
@@ -229,8 +231,8 @@ class Numeric
|
|
229
231
|
def to_hms_in_words
|
230
232
|
seconds = self
|
231
233
|
|
232
|
-
days,
|
233
|
-
hours,
|
234
|
+
days, seconds = seconds.divmod(86400)
|
235
|
+
hours, seconds = seconds.divmod(3600)
|
234
236
|
minutes, seconds = seconds.divmod(60)
|
235
237
|
seconds, frac = seconds.divmod(1)
|
236
238
|
|
@@ -243,6 +245,22 @@ class Numeric
|
|
243
245
|
result
|
244
246
|
end
|
245
247
|
|
248
|
+
def to_farenheit
|
249
|
+
(self * 9.0 / 5.0) + 32
|
250
|
+
end
|
251
|
+
|
252
|
+
def to_celcius
|
253
|
+
(self - 32) * 5.0 / 9.0
|
254
|
+
end
|
255
|
+
|
256
|
+
def to_lbs
|
257
|
+
self / 0.45359237
|
258
|
+
end
|
259
|
+
|
260
|
+
def to_kg
|
261
|
+
self * 0.45359237
|
262
|
+
end
|
263
|
+
|
246
264
|
end
|
247
265
|
|
248
266
|
|
@@ -442,7 +460,8 @@ end
|
|
442
460
|
class Prime
|
443
461
|
|
444
462
|
#
|
445
|
-
# Return an array of prime numbers within the specified range
|
463
|
+
# Return an array of prime numbers within the specified range.
|
464
|
+
# (It still has to generate all the primes less than the lower bound, so, yeah... be warned.)
|
446
465
|
#
|
447
466
|
def [](range)
|
448
467
|
ubound = range.end
|
@@ -130,10 +130,9 @@ class String
|
|
130
130
|
#
|
131
131
|
# Is there anything in the string? (ignoring whitespace/newlines)
|
132
132
|
#
|
133
|
-
def
|
133
|
+
def present?
|
134
134
|
not blank?
|
135
135
|
end
|
136
|
-
alias_method :present?, :any?
|
137
136
|
|
138
137
|
#
|
139
138
|
# Does this string contain something that means roughly "true"?
|
@@ -1,37 +1,47 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
|
-
|
3
|
+
class URI::Generic
|
4
4
|
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# Get the query string
|
7
7
|
#
|
8
|
-
def
|
9
|
-
|
8
|
+
def query
|
9
|
+
params.to_query
|
10
10
|
end
|
11
11
|
|
12
12
|
#
|
13
|
-
#
|
13
|
+
# Set the query string
|
14
14
|
#
|
15
|
-
def
|
16
|
-
|
15
|
+
def query=(new_query)
|
16
|
+
@params = new_query&.to_params
|
17
|
+
@query = new_query
|
17
18
|
end
|
18
19
|
|
19
20
|
#
|
20
|
-
#
|
21
|
+
# Return a Hash of the variables in the query string
|
21
22
|
#
|
22
|
-
def
|
23
|
-
|
24
|
-
current[key] = value
|
25
|
-
self.query = current.to_query
|
23
|
+
def params
|
24
|
+
@params ||= (@query ? @query.to_params : {})
|
26
25
|
end
|
27
26
|
|
28
27
|
#
|
29
|
-
#
|
28
|
+
# Update all the params at once
|
30
29
|
#
|
31
|
-
def
|
32
|
-
|
30
|
+
def params=(new_params)
|
31
|
+
# self.query = new_params.to_params
|
32
|
+
raise "params must be a Hash" unless new_params.is_a? Hash
|
33
|
+
@params = new_params
|
33
34
|
end
|
34
35
|
|
36
|
+
# #
|
37
|
+
# # Update one URI parameter
|
38
|
+
# #
|
39
|
+
# def set_param(key, value)
|
40
|
+
# current = params
|
41
|
+
# current[key] = value
|
42
|
+
# self.query = current.to_query
|
43
|
+
# end
|
44
|
+
|
35
45
|
#
|
36
46
|
# URIs *are* strings, dammit!
|
37
47
|
#
|
@@ -39,6 +49,10 @@ module URI
|
|
39
49
|
to_s
|
40
50
|
end
|
41
51
|
|
52
|
+
end
|
53
|
+
|
54
|
+
module URI
|
55
|
+
|
42
56
|
#
|
43
57
|
# Default user agent for the 'get' method
|
44
58
|
#
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
module Oga
|
3
|
+
module XML
|
4
|
+
# Serialize this node to HAML
|
5
|
+
module ElementToHAML
|
6
|
+
def to_haml
|
7
|
+
require 'html2haml'
|
8
|
+
require 'html2haml/html'
|
9
|
+
Html2haml::HTML.new(to_xml, {}).render.rstrip
|
10
|
+
end
|
11
|
+
alias_method :haml, :to_haml
|
12
|
+
|
13
|
+
def pretty
|
14
|
+
require 'coderay'
|
15
|
+
puts CodeRay.scan(haml, :haml).term
|
16
|
+
end
|
17
|
+
#alias_method :pp, :pretty
|
18
|
+
end
|
19
|
+
|
20
|
+
module PrettyNodeSet
|
21
|
+
def pretty
|
22
|
+
require 'coderay'
|
23
|
+
lesspipe(wrap: true) { |less| each { |node| less.puts CodeRay.scan(node.to_haml, :haml).term; less.puts; less.puts } }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Oga::XML::Element.include Oga::XML::ElementToHAML
|
31
|
+
Oga::XML::NodeSet.include Oga::XML::PrettyNodeSet
|
data/lib/epitools/job_runner.rb
CHANGED
@@ -26,11 +26,12 @@
|
|
26
26
|
# end
|
27
27
|
#
|
28
28
|
class JobRunner
|
29
|
-
def initialize(*blocks)
|
29
|
+
def initialize(*blocks, debug: false)
|
30
30
|
@threads = []
|
31
31
|
@results = Thread::Queue.new
|
32
32
|
@jobs = []
|
33
33
|
@started = false
|
34
|
+
@debug = debug
|
34
35
|
|
35
36
|
if blocks.any?
|
36
37
|
blocks.each { |block| add &block }
|
@@ -39,20 +40,37 @@ class JobRunner
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
def dmsg(msg)
|
44
|
+
puts "[#{Time.now}] #{msg}" if @debug
|
45
|
+
end
|
46
|
+
|
42
47
|
def add(&block)
|
48
|
+
dmsg("added job #{block}")
|
43
49
|
@jobs << block
|
44
50
|
end
|
45
51
|
|
46
52
|
def reap!
|
47
|
-
|
53
|
+
if @threads.any?
|
54
|
+
dmsg("reaping #{@threads.size} threads")
|
55
|
+
@threads.delete_if { |t| not t.alive? }
|
56
|
+
else
|
57
|
+
dmsg("reap failed: no threads")
|
58
|
+
end
|
48
59
|
end
|
49
60
|
|
50
61
|
def go!
|
51
|
-
|
62
|
+
if @started
|
63
|
+
raise "Error: already started"
|
64
|
+
else
|
65
|
+
dmsg("starting #{@threads.size} jobs")
|
66
|
+
end
|
67
|
+
|
52
68
|
@started = true
|
53
69
|
@jobs.each do |job|
|
70
|
+
dmsg("adding #{job}")
|
54
71
|
@threads << Thread.new do
|
55
72
|
@results << job.call
|
73
|
+
dmsg("job #{job} complete")
|
56
74
|
end
|
57
75
|
end
|
58
76
|
end
|
@@ -72,7 +90,7 @@ end
|
|
72
90
|
|
73
91
|
|
74
92
|
if __FILE__ == $0
|
75
|
-
JobRunner.new do |jr|
|
93
|
+
JobRunner.new(debug: true) do |jr|
|
76
94
|
jr.add { 3 }
|
77
95
|
jr.add { sleep 0.1; 2 }
|
78
96
|
jr.add { sleep 0.2; 1 }
|
data/lib/epitools/numwords.rb
CHANGED
data/lib/epitools/path.rb
CHANGED
@@ -119,11 +119,20 @@ class Path
|
|
119
119
|
# The file extension, including the . (eg: ".mp3")
|
120
120
|
attr_reader :ext
|
121
121
|
|
122
|
+
URI_RE = %r{^[a-z\-]+://}i
|
122
123
|
|
123
124
|
###############################################################################
|
124
125
|
# Initializers
|
125
126
|
###############################################################################
|
126
127
|
|
128
|
+
def self.new(*args)
|
129
|
+
if args.first =~ URI_RE and self != Path::URI
|
130
|
+
Path::URI.new(args.first)
|
131
|
+
else
|
132
|
+
super(*args)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
127
136
|
def initialize(newpath, hints={})
|
128
137
|
send("path=", newpath, hints)
|
129
138
|
|
@@ -156,8 +165,8 @@ class Path
|
|
156
165
|
path
|
157
166
|
when String
|
158
167
|
|
159
|
-
if path =~
|
160
|
-
Path
|
168
|
+
if path =~ URI_RE
|
169
|
+
Path.new(path)
|
161
170
|
|
162
171
|
else
|
163
172
|
# TODO: highlight backgrounds of codeblocks to show indent level & put boxes (or rules?) around (between?) double-spaced regions
|
@@ -186,7 +195,7 @@ class Path
|
|
186
195
|
# Note: The `hints` parameter contains options so `path=` doesn't have to touch the filesytem as much.
|
187
196
|
#
|
188
197
|
def path=(newpath, hints={})
|
189
|
-
if hints[:type] or File.
|
198
|
+
if hints[:type] or File.exist? newpath
|
190
199
|
if hints[:type] == :dir or File.directory? newpath
|
191
200
|
self.dir = newpath
|
192
201
|
else
|
@@ -357,7 +366,7 @@ class Path
|
|
357
366
|
###############################################################################
|
358
367
|
|
359
368
|
def exists?
|
360
|
-
File.
|
369
|
+
File.exist? path
|
361
370
|
end
|
362
371
|
|
363
372
|
def size
|
@@ -430,7 +439,7 @@ class Path
|
|
430
439
|
end
|
431
440
|
|
432
441
|
def broken_symlink?
|
433
|
-
File.symlink?(path) and not File.
|
442
|
+
File.symlink?(path) and not File.exist?(path)
|
434
443
|
end
|
435
444
|
|
436
445
|
def symlink_target
|
@@ -930,7 +939,7 @@ class Path
|
|
930
939
|
|
931
940
|
# Parse the file as CSV
|
932
941
|
def read_csv(io=self.io, opts={})
|
933
|
-
|
942
|
+
CSV.new(io.read, **opts).each
|
934
943
|
end
|
935
944
|
alias_method :from_csv, :read_csv
|
936
945
|
|
@@ -1638,9 +1647,9 @@ class Path::URI < Path
|
|
1638
1647
|
#
|
1639
1648
|
# When this is: http://host.com:port/path/filename.ext?param1=value1¶m2=value2&...
|
1640
1649
|
#
|
1641
|
-
def to_s
|
1642
|
-
|
1643
|
-
end
|
1650
|
+
def to_s; uri.to_s; end
|
1651
|
+
def to_path; to_s; end
|
1652
|
+
def to_str; to_s; end
|
1644
1653
|
|
1645
1654
|
def inspect
|
1646
1655
|
"#<Path::URI:#{to_s}>"
|
@@ -1693,9 +1702,9 @@ class Path::URI < Path
|
|
1693
1702
|
def open(mode="r", &block)
|
1694
1703
|
require 'open-uri'
|
1695
1704
|
if block_given?
|
1696
|
-
|
1705
|
+
::URI.open(to_s, mode, &block)
|
1697
1706
|
else
|
1698
|
-
|
1707
|
+
::URI.open(to_s, mode)
|
1699
1708
|
end
|
1700
1709
|
end
|
1701
1710
|
|
data/lib/epitools/sys.rb
CHANGED
data/spec/core_ext_spec.rb
CHANGED
@@ -127,26 +127,6 @@ end
|
|
127
127
|
|
128
128
|
describe Class do
|
129
129
|
|
130
|
-
it "uses" do
|
131
|
-
module Test1
|
132
|
-
def test1; :test1; end
|
133
|
-
end
|
134
|
-
|
135
|
-
module Test2
|
136
|
-
def test2; :test2; end
|
137
|
-
end
|
138
|
-
|
139
|
-
Hash.using(Test1).new.test1.should == :test1
|
140
|
-
Hash.using(Test2).new.test2.should == :test2
|
141
|
-
h = Hash.using(Test1, Test2).new
|
142
|
-
h.test1.should == :test1
|
143
|
-
h.test2.should == :test2
|
144
|
-
|
145
|
-
Hash.using(Test1) do |h|
|
146
|
-
h.new.test1.should == :test1
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
130
|
it "traces messages (when $DEBUG is set)" do
|
151
131
|
$DEBUG = true
|
152
132
|
|
@@ -166,10 +146,10 @@ describe Class do
|
|
166
146
|
class ButtTest
|
167
147
|
trace_messages_to :*
|
168
148
|
|
169
|
-
def
|
149
|
+
def a
|
170
150
|
end
|
171
151
|
|
172
|
-
def
|
152
|
+
def b
|
173
153
|
end
|
174
154
|
end
|
175
155
|
|
@@ -197,7 +177,7 @@ describe Numeric do
|
|
197
177
|
-12983287123.commatize.should == "-12,983,287,123"
|
198
178
|
-12983287123.4411.commatize.should == "-12,983,287,123.4411"
|
199
179
|
1111.1234567.commatize.should == "1,111.1234567"
|
200
|
-
BigDecimal
|
180
|
+
BigDecimal("1111.1234567").commatize.should == "1,111.1234567"
|
201
181
|
-1234567.1234567.underscorize.should == "-1_234_567.1234567"
|
202
182
|
end
|
203
183
|
|
@@ -237,6 +217,11 @@ describe Numeric do
|
|
237
217
|
32583128.human_size(2).should == "31.07MB"
|
238
218
|
end
|
239
219
|
|
220
|
+
it "temperatures" do
|
221
|
+
t = 18.0
|
222
|
+
t.to_farenheit.to_celcius.should be_within(0.001).of(t)
|
223
|
+
end
|
224
|
+
|
240
225
|
end
|
241
226
|
|
242
227
|
|
@@ -1311,18 +1296,24 @@ describe URI do
|
|
1311
1296
|
uri.params.should == opts
|
1312
1297
|
end
|
1313
1298
|
|
1314
|
-
it "gets" do
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
end
|
1299
|
+
# it "gets" do
|
1300
|
+
# response = URI("http://google.com/").get
|
1301
|
+
# response.body.size
|
1302
|
+
# (response.size > 0).should == true
|
1303
|
+
# end
|
1319
1304
|
|
1320
1305
|
it "params=" do
|
1321
|
-
u = "http://butt.
|
1306
|
+
u = "http://butt.cx/?q=1".to_uri
|
1322
1307
|
u.query.should == "q=1"
|
1308
|
+
u.params.should == {"q" => "1"}
|
1323
1309
|
u.params["q"] = 2
|
1324
1310
|
u.params["q"].should == 2
|
1311
|
+
u.params.should == {"q" => 2}
|
1325
1312
|
u.query.should == "q=2"
|
1313
|
+
|
1314
|
+
subbed = u.with(query: u.params.reject{|k,v| u.params.keys.include? 'q' }.to_query)
|
1315
|
+
subbed.params.should == {}
|
1316
|
+
subbed.query.should == ""
|
1326
1317
|
end
|
1327
1318
|
|
1328
1319
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: epitools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.134
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- epitron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- lib/epitools/core_ext/truthiness.rb
|
70
70
|
- lib/epitools/core_ext/uri.rb
|
71
71
|
- lib/epitools/daemonize.rb
|
72
|
+
- lib/epitools/gem_ext/oga.rb
|
72
73
|
- lib/epitools/hexdump.rb
|
73
74
|
- lib/epitools/iter.rb
|
74
75
|
- lib/epitools/its.rb
|
@@ -142,7 +143,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
143
|
- !ruby/object:Gem::Version
|
143
144
|
version: '0'
|
144
145
|
requirements: []
|
145
|
-
rubygems_version: 3.
|
146
|
+
rubygems_version: 3.2.21
|
146
147
|
signing_key:
|
147
148
|
specification_version: 3
|
148
149
|
summary: Not utils... METILS!
|