epitools 0.5.123 → 0.5.129

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
  SHA256:
3
- metadata.gz: 11a6ae70a9142d18e741ba903f803f7977d0281db3478fb2c39b32d53044d0ed
4
- data.tar.gz: 5dea125fb921bb2ad59c08fa7ffc6f32f03c3fafd03736ea124b4c5a72c2ff09
3
+ metadata.gz: 74b341f10e9697a2d9e93aad5aa91b7f799e75a3cd817d712bce3e15cd18428d
4
+ data.tar.gz: bce241006bd3b743410e3b6833145a5e72052637d7e918caa2562564b6ad4f5b
5
5
  SHA512:
6
- metadata.gz: da43a98210212a18a6837a53951ac813ccc2a41f64900e559c352ef0f40ea84764671a7148e2dc8a642331d0b1c0fa73d164f19a9fc06135d40a3a35abfb3d7f
7
- data.tar.gz: b32f798ac765857e2490fc9ee7f78f5c251e0a53658493f203c06dbb30df4f7e77fb023b8fa865951ed12036be2c638ce2ac8aef20fee430e5ec1f6bc2797957
6
+ metadata.gz: ef8edebf3480e814c17e90f5c200fe1dc70a45827d8c2e52d2d7834291f61fb67824c5c5b6f869805f8751ea53d0eb95aa83e86daba42eb748d34ea66061ad6a
7
+ data.tar.gz: 38abf237811351f91306dd1d1e66e9104040645aa3ff743d13609a155853aa6ffa80b9967961edda5f20e1ad67068ffc298beafac47857210eca9ebb6a4ec87f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.123
1
+ 0.5.129
@@ -1,7 +1,6 @@
1
1
  ## Standard library
2
2
 
3
3
  autoload :Set, 'set'
4
- autoload :URI, 'uri'
5
4
  autoload :Zlib, 'zlib'
6
5
  autoload :FileUtils, 'fileutils'
7
6
  autoload :Tempfile, 'tempfile'
@@ -23,6 +22,10 @@ autoload :CSV, 'csv'
23
22
  autoload :SDBM, 'sdbm'
24
23
  autoload :StringScanner, 'strscan'
25
24
 
25
+ autoreq :URI do
26
+ require 'epitools/core_ext/uri'
27
+ end
28
+
26
29
  module Digest
27
30
  autoload :SHA1, 'digest/sha1'
28
31
  autoload :SHA2, 'digest/sha2'
@@ -62,26 +65,32 @@ autoload :IPAddr, 'ipaddr'
62
65
 
63
66
  ## Nonstandard library (epitools)
64
67
 
65
- autoload :Path, 'epitools/path'
66
- autoload :Ezdb, 'epitools/ezdb'
67
- autoload :Browser, 'epitools/browser'
68
- autoload :Rash, 'epitools/rash'
69
- autoload :Ratio, 'epitools/ratio'
70
- autoload :ProgressBar, 'epitools/progressbar'
71
- autoload :Trie, 'epitools/trie'
72
- autoload :MimeMagic, 'epitools/mimemagic'
73
- autoload :Term, 'epitools/term'
74
- autoload :Iter, 'epitools/iter'
75
- autoload :WM, 'epitools/wm'
76
- autoload :TypedStruct, 'epitools/typed_struct'
77
- autoload :Sys, 'epitools/sys'
68
+ autoload :Path, 'epitools/path'
69
+ autoload :Ezdb, 'epitools/ezdb'
70
+ autoload :Browser, 'epitools/browser'
71
+ autoload :Rash, 'epitools/rash'
72
+ autoload :Ratio, 'epitools/ratio'
73
+ autoload :ProgressBar, 'epitools/progressbar'
74
+ autoload :Trie, 'epitools/trie'
75
+ autoload :MimeMagic, 'epitools/mimemagic'
76
+ autoload :Term, 'epitools/term'
77
+ autoload :Iter, 'epitools/iter'
78
+ autoload :WM, 'epitools/wm'
79
+ autoload :TypedStruct, 'epitools/typed_struct'
80
+ autoload :Sys, 'epitools/sys'
81
+ autoload :JobRunner, 'epitools/job_runner'
78
82
  autoload :SemanticVersion, 'epitools/semantic_version'
79
83
 
80
84
  autoload :Matrix, 'epitools/core_ext/matrix'
81
85
  autoreq(:Vector) { Matrix }
82
86
 
83
- module Epi; autoload :Slop, 'epitools/slop'; end
84
- autoreq(:Slop) { Slop = Epi::Slop }
87
+ ## Bundled slop
88
+ module Epi
89
+ autoload :Slop, 'epitools/slop'
90
+ end
91
+ autoreq(:Slop) do
92
+ Slop = Epi::Slop
93
+ end
85
94
 
86
95
  ## Gems (common)
87
96
 
@@ -230,3 +230,20 @@ def notify_send(title, body=nil, icon: nil, time: 5)
230
230
  fork { system *cmd }
231
231
  end
232
232
 
233
+ def curl(url)
234
+ curl_open(url).read
235
+ end
236
+
237
+ def curl_open(url, headers={})
238
+ # headers["User-Agent"] ||= "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/85 Version/11.1.1 Safari/605.1.15"
239
+ cmd = ["curl", "-LSs"]
240
+ headers.each { |k,v| cmd += ["-H", "#{k}: #{v}"] }
241
+ cmd << url
242
+ IO.popen(cmd)
243
+ rescue Errno::ENOENT
244
+ raise "Error: 'curl' isn't installed."
245
+ end
246
+
247
+ def curl_json(url)
248
+ JSON.parse(curl(url))
249
+ end
@@ -5,16 +5,23 @@ require 'epitools'
5
5
  require 'epitools/core_ext/object'
6
6
  require 'epitools/core_ext/class'
7
7
  require 'epitools/core_ext/module'
8
+
8
9
  require 'epitools/core_ext/string'
10
+
9
11
  require 'epitools/core_ext/array'
10
- require 'epitools/core_ext/file'
11
- require 'epitools/core_ext/io'
12
12
  require 'epitools/core_ext/enumerable'
13
13
  require 'epitools/core_ext/hash'
14
+
14
15
  require 'epitools/core_ext/numbers'
15
16
  require 'epitools/core_ext/truthiness'
16
17
  require 'epitools/core_ext/range'
17
18
  require 'epitools/core_ext/time'
19
+
20
+ require 'epitools/core_ext/argv'
21
+ require 'epitools/core_ext/file'
22
+ require 'epitools/core_ext/io'
23
+ require 'epitools/core_ext/uri'
24
+
18
25
  require 'epitools/core_ext/misc'
19
26
 
20
27
  ##############################################################################
@@ -0,0 +1,59 @@
1
+ class << ARGV
2
+
3
+ def parse!
4
+ unless @opts or @args
5
+ @opts, @args = partition { |arg| arg[/^--?\w{1,2}/].nil? }
6
+ @opts = @opts.map { |opt| key, val = opt.strip(/^-+/).split("=") }.to_ostruct
7
+ if @opts.help
8
+ @help_handler.call
9
+ exit
10
+ end
11
+ end
12
+
13
+ [@opts, @args]
14
+ end
15
+
16
+ def parse
17
+ parse!
18
+ [@opts, @args]
19
+ end
20
+
21
+ def help?
22
+ !!@opts["help"]
23
+ end
24
+
25
+ def opts
26
+ parse! unless @opts
27
+ @opts
28
+ end
29
+
30
+ def args
31
+ @args ? @args : opts && @args
32
+ end
33
+
34
+ def paths
35
+ map(&:to_Path)
36
+ end
37
+
38
+ def paths_R
39
+ recursive_proc = proc do |paths|
40
+ paths.map { |path| path.dir? ? the_expander.(path.ls_R) : path }
41
+ end
42
+
43
+ recursive_proc.(paths)
44
+ end
45
+ alias_method :recursive_paths, :paths_R
46
+
47
+ def on_help(&block)
48
+ @help_handler = block
49
+ end
50
+
51
+ def regexes(escaped: true, case_sensitive: false)
52
+ if case_sensitive
53
+ map { |arg| /#{escaped ? Regexp.escape(arg) : arg}/ } # NO 'i'
54
+ else
55
+ map { |arg| /#{escaped ? Regexp.escape(arg) : arg}/i }
56
+ end
57
+ end
58
+
59
+ end
@@ -324,6 +324,33 @@ class Array
324
324
  super.to_a
325
325
  end
326
326
 
327
- end
327
+ module ToCSV
328
+ #
329
+ # Convert this enumerable into a CSV string (nb: enumerable must contain either all Hashes or all Arrays)
330
+ #
331
+ def to_csv(delimiter=",")
332
+ types = count_by(&:class)
333
+
334
+ unless types.size == 1 and (types[Array] > 0 or types[Hash] > 0)
335
+ raise "Error: this array must contain nothing but arrays, or nothing but hashes (actually contains: #{types.inspect})"
336
+ end
337
+
338
+ options = {}
339
+ options[:col_sep] = delimiter
340
+ options[:headers] = flat_map(&:keys).uniq if types[Hash] > 0
328
341
 
342
+ CSV.generate(nil, **options) do |csv|
343
+ each { |obj| csv << obj }
344
+ end
345
+ end
329
346
 
347
+ #
348
+ # Like #to_csv, but with tab-separated CSV fields
349
+ #
350
+ def to_tsv
351
+ to_csv("\t")
352
+ end
353
+ end
354
+
355
+ prepend ToCSV # dirty hack to stop the CSV module from clobbering the to_csv method
356
+ end
@@ -1,4 +1,7 @@
1
+ require 'epitools/core_ext/array'
2
+
1
3
  module Enumerable
4
+ include Array::ToCSV
2
5
 
3
6
  #
4
7
  # 'true' if the Enumerable has no elements
@@ -128,79 +128,6 @@ end
128
128
 
129
129
 
130
130
 
131
- module URI
132
-
133
- #
134
- # Return a Hash of the variables in the query string
135
- #
136
- def params
137
- query ? query.to_params : {}
138
- end
139
-
140
- #
141
- # URIs are strings, dammit!
142
- #
143
- def to_str
144
- to_s
145
- end
146
-
147
- #
148
- # Default user agent for the 'get' method
149
- #
150
- # USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0"
151
-
152
- #
153
- # Get this URI using Net::HTTP
154
- #
155
- def get(headers={}, redirect_limit=10)
156
- raise "Sorry, URI can't get from #{scheme.inspect} URIs yet" unless scheme =~ /^https?$/
157
- raise 'Too many HTTP redirections' if redirect_limit == 0
158
-
159
- # headers['User-Agent'] ||= USER_AGENT
160
-
161
- # response = Net::HTTP.start(host, port) do |http|
162
- # # the_path = path.empty? ? "/" : path
163
- # req = Net::HTTP::Get.new(self, headers)
164
- # http.request(req)
165
- # end
166
-
167
- response = Net::HTTP.get_response(self)
168
-
169
- case response
170
- when Net::HTTPSuccess
171
- response
172
- when Net::HTTPRedirection
173
- # puts "redirect: #{response['location']}"
174
- URI(response['location']).get(headers, redirect_limit-1)
175
- else
176
- response.error!
177
- end
178
- end
179
-
180
- end
181
-
182
- #
183
- # Stupid workaround for URI blowing up when it receives a [ or ] character
184
- #
185
- module Better_URI_RFC3986_Parser # ::RFC3986_relative_ref
186
- ESCAPE_ME_PLZ = "[]{}!"
187
-
188
- def split(uri)
189
- subsitutions = ESCAPE_ME_PLZ.chars.map { |c| [c, CGI.escape(c)] }
190
- subsitutions << [" ", "%20"]
191
-
192
- subsitutions.each do |find, replace|
193
- uri = uri.gsub(find, replace)
194
- end
195
-
196
- super(uri)
197
- end
198
-
199
- end
200
-
201
- URI::RFC3986_Parser.prepend(Better_URI_RFC3986_Parser)
202
-
203
-
204
131
 
205
132
  #
206
133
  # Give ObjectSpace Enumerable powers (select, map, etc.)
@@ -0,0 +1,97 @@
1
+ require 'uri'
2
+
3
+ module URI
4
+
5
+ #
6
+ # Return a Hash of the variables in the query string
7
+ #
8
+ def params
9
+ (@query ? @query.to_params : {})
10
+ end
11
+
12
+ #
13
+ # Update all the params at once
14
+ #
15
+ def params=(new_params)
16
+ self.query = new_params.to_params
17
+ end
18
+
19
+ #
20
+ # Update one URI parameter
21
+ #
22
+ def set_param(key, value)
23
+ current = params
24
+ current[key] = value
25
+ self.query = current.to_query
26
+ end
27
+
28
+ #
29
+ # Get the query string
30
+ #
31
+ def query
32
+ params.to_query
33
+ end
34
+
35
+ #
36
+ # URIs *are* strings, dammit!
37
+ #
38
+ def to_str
39
+ to_s
40
+ end
41
+
42
+ #
43
+ # Default user agent for the 'get' method
44
+ #
45
+ # USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0"
46
+
47
+ #
48
+ # Get this URI using Net::HTTP
49
+ #
50
+ def get(headers={}, redirect_limit=10)
51
+ raise "Sorry, URI can't get from #{scheme.inspect} URIs yet" unless scheme =~ /^https?$/
52
+ raise 'Too many HTTP redirections' if redirect_limit == 0
53
+
54
+ # headers['User-Agent'] ||= USER_AGENT
55
+
56
+ # response = Net::HTTP.start(host, port) do |http|
57
+ # # the_path = path.empty? ? "/" : path
58
+ # req = Net::HTTP::Get.new(self, headers)
59
+ # http.request(req)
60
+ # end
61
+
62
+ response = Net::HTTP.get_response(self)
63
+
64
+ case response
65
+ when Net::HTTPSuccess
66
+ response
67
+ when Net::HTTPRedirection
68
+ # puts "redirect: #{response['location']}"
69
+ URI(response['location']).get(headers, redirect_limit-1)
70
+ else
71
+ response.error!
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ #
78
+ # Stupid workaround for URI blowing up when it receives a [ or ] character
79
+ #
80
+ module Better_URI_RFC3986_Parser # ::RFC3986_relative_ref
81
+ ESCAPE_ME_PLZ = "[]{}!"
82
+
83
+ def split(uri)
84
+ subsitutions = ESCAPE_ME_PLZ.chars.map { |c| [c, CGI.escape(c)] }
85
+ subsitutions << [" ", "%20"]
86
+
87
+ subsitutions.each do |find, replace|
88
+ uri = uri.gsub(find, replace)
89
+ end
90
+
91
+ super(uri)
92
+ end
93
+
94
+ end
95
+
96
+ URI::RFC3986_Parser.prepend(Better_URI_RFC3986_Parser)
97
+
@@ -0,0 +1,97 @@
1
+ #
2
+ # Runs many jobs in parallel, and returns their interleaved results.
3
+ # (NOTE: The JobRunner can be run multiple times; each time the blocks
4
+ # will be executed again.)
5
+ #
6
+ # Examples:
7
+ #
8
+ # JobRunner.new do |jr|
9
+ # jr.add { 3 }
10
+ # jr.add { sleep 0.1; 2 }
11
+ # jr.add { sleep 0.2; 1 }
12
+ #
13
+ # jr.each_result do |result|
14
+ # p result
15
+ # end
16
+ # end
17
+ #
18
+ # jr = JobRunner.new(
19
+ # proc { 1 },
20
+ # proc { 2 },
21
+ # proc { 3 }
22
+ # )
23
+ #
24
+ # 2.times do
25
+ # jr.each_result { |result| p result }
26
+ # end
27
+ #
28
+ class JobRunner
29
+ def initialize(*blocks)
30
+ @threads = []
31
+ @results = Thread::Queue.new
32
+ @jobs = []
33
+ @started = false
34
+
35
+ if blocks.any?
36
+ blocks.each { |block| add &block }
37
+ else
38
+ yield self if block_given?
39
+ end
40
+ end
41
+
42
+ def add(&block)
43
+ @jobs << block
44
+ end
45
+
46
+ def reap!
47
+ @threads.delete_if { |t| not t.alive? } if @threads.any?
48
+ end
49
+
50
+ def go!
51
+ raise "Error: already started" if @started
52
+ @started = true
53
+ @jobs.each do |job|
54
+ @threads << Thread.new do
55
+ @results << job.call
56
+ end
57
+ end
58
+ end
59
+
60
+ def each_result
61
+ go! unless @started
62
+
63
+ loop do
64
+ yield @results.pop
65
+ reap!
66
+ break if @threads.empty? and @results.empty?
67
+ end
68
+
69
+ @started = false
70
+ end
71
+ end
72
+
73
+
74
+ if __FILE__ == $0
75
+ JobRunner.new do |jr|
76
+ jr.add { 3 }
77
+ jr.add { sleep 0.1; 2 }
78
+ jr.add { sleep 0.2; 1 }
79
+
80
+ jr.each_result do |result|
81
+ p result
82
+ end
83
+ end
84
+
85
+ puts
86
+
87
+ jr = JobRunner.new(
88
+ proc { 1 },
89
+ proc { 2 },
90
+ proc { 3 }
91
+ )
92
+
93
+ 2.times do
94
+ jr.each_result { |r| p r }
95
+ puts
96
+ end
97
+ end
@@ -1,8 +1,10 @@
1
+ ####################################################################################
1
2
  #
2
3
  # If you require 'epitools/minimal' instead of 'epitools',
3
4
  # this is what you get: core_ext monkeypatches and all the
4
5
  # autoloads; the barest essentials for survival.
5
6
  #
7
+ ####################################################################################
6
8
 
7
9
  if RUBY_VERSION[/^1.8/]
8
10
  require 'enumerator'
@@ -14,6 +16,7 @@ RbConfig = Config unless defined? RbConfig
14
16
  Infinity = Float::INFINITY
15
17
  Inf = Float::INFINITY
16
18
 
19
+ ####################################################################################
17
20
  class Object
18
21
 
19
22
  unless defined?(__DIR__)
@@ -164,14 +167,13 @@ class Object
164
167
  #
165
168
  # eg: stuff.group_by(&:self)
166
169
  #
167
- define_method :self do
170
+ def self
168
171
  if block_given?
169
172
  yield self
170
173
  else
171
174
  self
172
175
  end
173
176
  end
174
- alias_method :fap, :self
175
177
 
176
178
  def ancestors
177
179
  self.class.ancestors
@@ -179,6 +181,7 @@ class Object
179
181
  end
180
182
 
181
183
 
184
+ ####################################################################################
182
185
  #
183
186
  # Patch 'Module#const_missing' to support 'autoreq' (which can autoload gems)
184
187
  #
@@ -213,6 +216,8 @@ class Module
213
216
  end
214
217
 
215
218
 
219
+
220
+ ####################################################################################
216
221
  module Kernel
217
222
 
218
223
  #
@@ -254,10 +259,8 @@ module Kernel
254
259
  end
255
260
 
256
261
  end
257
- ####################################################################################
258
-
259
-
260
262
 
263
+ ####################################################################################
261
264
  class String
262
265
 
263
266
  #
@@ -270,6 +273,7 @@ class String
270
273
 
271
274
  end
272
275
 
276
+ ####################################################################################
273
277
  #
274
278
  # Path("/some/path") is an alias for Path["/some/path"]
275
279
  #
@@ -277,43 +281,7 @@ def Path(arg)
277
281
  Path[arg]
278
282
  end
279
283
 
280
- ####################################################################
281
-
282
- # class << ARGV
283
-
284
- # def opts
285
- # @opts, @args ||= partition { |arg| arg[/^--?\w{1,2}/].nil? }
286
- # end
287
-
288
- # def args
289
- # @args ? @args : opts && @args
290
- # end
291
-
292
- # def paths
293
- # map(&:to_Path)
294
- # end
295
-
296
- # def paths_R
297
- # recursive_proc = proc do |paths|
298
- # paths.map { |path| path.dir? ? the_expander.(path.ls_R) : path }
299
- # end
300
-
301
- # recursive_proc.(paths)
302
- # end
303
- # alias_method :recursive_paths, :paths_R
304
-
305
- # def regexes(escaped: true, case_sensitive: false)
306
- # if case_sensitive
307
- # map { |arg| /#{escaped ? Regexp.escape(arg) : arg}/ } # NO 'i'
308
- # else
309
- # map { |arg| /#{escaped ? Regexp.escape(arg) : arg}/i }
310
- # end
311
- # end
312
-
313
- # end
314
284
 
315
285
  ####################################################################
316
-
317
286
  require 'epitools/autoloads'
318
-
319
287
  ####################################################################
@@ -117,6 +117,7 @@ class Numeric
117
117
  factor = 10**pow
118
118
 
119
119
  if is_a?(Float)
120
+ BigDecimal
120
121
  (BigDecimal(to_s) * factor).to_i
121
122
  else
122
123
  self * factor
@@ -1110,6 +1110,25 @@ class Path
1110
1110
  }
1111
1111
  end
1112
1112
 
1113
+ #
1114
+ # Path.mkcd(path) creates a path if it doesn't exist, and changes to it (temporarily, if a block is provided)
1115
+ #
1116
+ def self.mkcd(path, &block)
1117
+ path = path.to_Path unless path.is_a? Path
1118
+ path.mkdir_p unless path.exists?
1119
+
1120
+ raise "Error: #{path} couldn't be created." unless path.dir?
1121
+
1122
+ self.cd(path, &block)
1123
+ end
1124
+
1125
+ #
1126
+ # Path.mkcd(self)
1127
+ #
1128
+ def mkcd(&block)
1129
+ Path.mkcd(self, &block)
1130
+ end
1131
+
1113
1132
  def cp_r(dest)
1114
1133
  FileUtils.cp_r(path, dest) #if Path[dest].exists?
1115
1134
  dest
@@ -61,7 +61,7 @@ module WM
61
61
 
62
62
  def self.all
63
63
  # FIXME: Windows owned by linux-namespaced processes (firejail) report their namspaced pid to X11. `window.process` ends up pointing at either nil, or the wrong process.
64
- `wmctrl -lpG`.lines.map(&:strip).map { |line| Window.from_line(line) }
64
+ `wmctrl -lpG`.lines.map(&:strip).map { |line| Window.from_line(line) unless line.blank? }.compact
65
65
  end
66
66
 
67
67
  def self.from_line(line)
@@ -147,6 +147,44 @@ describe Class do
147
147
  end
148
148
  end
149
149
 
150
+ it "traces messages (when $DEBUG is set)" do
151
+ $DEBUG = true
152
+
153
+ class TestButt
154
+ trace_messages_to :a, :b, :c
155
+
156
+ def a(x)
157
+ end
158
+
159
+ def b(x)
160
+ end
161
+
162
+ def c(x,y,z,&block)
163
+ end
164
+ end
165
+
166
+ class ButtTest
167
+ trace_messages_to :*
168
+
169
+ def d
170
+ end
171
+
172
+ def e
173
+ end
174
+ end
175
+
176
+ t = TestButt.new
177
+ t.a(1)
178
+ t.b(2)
179
+ t.c(3,4,5) { :butt }
180
+
181
+ b = ButtTest.new
182
+ b.a
183
+ b.b
184
+
185
+ $DEBUG = false
186
+ end
187
+
150
188
  end
151
189
 
152
190
 
@@ -757,6 +795,38 @@ describe Enumerable do
757
795
  ps.sort_numerically.map(&:filename).should == proper
758
796
  end
759
797
 
798
+ it "to_csvs and to_tsvs" do
799
+ data = [
800
+ ["1", "2", "3"],
801
+ ["4", "5", "6"],
802
+ ["7", "8", "9", "10"],
803
+ ]
804
+
805
+ hash_data = [
806
+ {a: 1, b: 2, c: 3},
807
+ {a: 4, b: 5, c: 6},
808
+ {a: 7, b: 8, c: 9, d: 10},
809
+ ]
810
+
811
+ class EnumedData
812
+ include Enumerable
813
+ def initialize(data); @data=data; end
814
+ def each(&block); @data.each(&block); end
815
+ end
816
+
817
+ [data, hash_data, EnumedData.new(data)].each do |a|
818
+ str = a.to_csv
819
+ str.each_line.count.should == 3
820
+ str.should_not be_nil
821
+ str["1,2,3"].should_not be_nil
822
+
823
+ str = a.to_tsv
824
+ str.should_not be_nil
825
+ str["1\t2\t3"].should_not be_nil
826
+ end
827
+
828
+ end
829
+
760
830
  end
761
831
 
762
832
 
@@ -1204,6 +1274,16 @@ describe File do
1204
1274
 
1205
1275
  end
1206
1276
 
1277
+ describe ARGV do
1278
+
1279
+ # it "parses args" do
1280
+ # ARGV.clear
1281
+ # ARGV << "-d"
1282
+ # ARGV.parse!
1283
+ # p ARGV.opts
1284
+ # end
1285
+
1286
+ end
1207
1287
 
1208
1288
  describe "Anything" do
1209
1289
 
@@ -1237,5 +1317,13 @@ describe URI do
1237
1317
  (response.size > 0).should == true
1238
1318
  end
1239
1319
 
1320
+ it "params=" do
1321
+ u = "http://butt.com/?q=1".to_uri
1322
+ u.query.should == "q=1"
1323
+ u.params["q"] = 2
1324
+ u.params["q"].should == 2
1325
+ u.query.should == "q=2"
1326
+ end
1327
+
1240
1328
  end
1241
1329
 
@@ -348,6 +348,25 @@ describe Path do
348
348
  lambda { tmp2.mkdir_p }.should_not raise_error
349
349
  end
350
350
 
351
+ it "mkcds" do
352
+ tmp = Path.tmpdir
353
+ tmp.dir?.should == true
354
+ tmp.rm
355
+ tmp.exists?.should == false
356
+
357
+ Path.mkcd(tmp) do
358
+ Path.pwd.path.should == tmp.path
359
+ end
360
+
361
+ tmp.rm
362
+
363
+ tmp.mkcd do
364
+ Path.pwd.path.should == tmp.path
365
+ end
366
+
367
+ tmp.rm
368
+ end
369
+
351
370
  it "has classmethods" do
352
371
  path = Path.tmpfile
353
372
 
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.123
4
+ version: 0.5.129
5
5
  platform: ruby
6
6
  authors:
7
7
  - epitron
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-28 00:00:00.000000000 Z
11
+ date: 2020-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -51,6 +51,7 @@ files:
51
51
  - lib/epitools/clitools.rb
52
52
  - lib/epitools/colored.rb
53
53
  - lib/epitools/core_ext.rb
54
+ - lib/epitools/core_ext/argv.rb
54
55
  - lib/epitools/core_ext/array.rb
55
56
  - lib/epitools/core_ext/class.rb
56
57
  - lib/epitools/core_ext/enumerable.rb
@@ -66,10 +67,12 @@ files:
66
67
  - lib/epitools/core_ext/string.rb
67
68
  - lib/epitools/core_ext/time.rb
68
69
  - lib/epitools/core_ext/truthiness.rb
70
+ - lib/epitools/core_ext/uri.rb
69
71
  - lib/epitools/daemonize.rb
70
72
  - lib/epitools/hexdump.rb
71
73
  - lib/epitools/iter.rb
72
74
  - lib/epitools/its.rb
75
+ - lib/epitools/job_runner.rb
73
76
  - lib/epitools/lcs.rb
74
77
  - lib/epitools/mimemagic.rb
75
78
  - lib/epitools/mimemagic_tables.rb
@@ -124,7 +127,7 @@ homepage: http://github.com/epitron/epitools
124
127
  licenses:
125
128
  - WTFPL
126
129
  metadata: {}
127
- post_install_message:
130
+ post_install_message:
128
131
  rdoc_options: []
129
132
  require_paths:
130
133
  - lib
@@ -139,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
142
  - !ruby/object:Gem::Version
140
143
  version: '0'
141
144
  requirements: []
142
- rubygems_version: 3.0.4
143
- signing_key:
145
+ rubygems_version: 3.1.4
146
+ signing_key:
144
147
  specification_version: 3
145
148
  summary: Not utils... METILS!
146
149
  test_files: []