epitools 0.4.37 → 0.4.38

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.37
1
+ 0.4.38
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epitools}
8
- s.version = "0.4.37"
8
+ s.version = "0.4.38"
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-29}
12
+ s.date = %q{2011-06-07}
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 = [
@@ -2,6 +2,7 @@ require 'pp'
2
2
  require 'set'
3
3
 
4
4
  class Object
5
+
5
6
  unless defined?(__DIR__)
6
7
  #
7
8
  # This method is convenience for the `File.expand_path(File.dirname(__FILE__))` idiom.
@@ -13,8 +14,64 @@ class Object
13
14
  ::File.expand_path(::File.join(dir, *args.map{|a| a.to_s}))
14
15
  end
15
16
  end
17
+
18
+ #
19
+ # 'autoreq' is a replacement for autoload that can load gems.
20
+ #
21
+ # Usage:
22
+ # autoreq :Constant, 'thing-to-require'
23
+ # autoreq :Constant, 'thing-to-require'
24
+ # autoreq :OtherConstant do
25
+ # gem 'somegem', '~> 1.2'
26
+ # require 'somegem'
27
+ # end
28
+ #
29
+ def autoreq(const, path=nil, &block)
30
+ raise "Error: autoreq must be supplied with a file to load, or a block." unless !!path ^ block_given?
31
+
32
+ if block_given?
33
+ Module.autoreqs[const] = block
34
+ else
35
+ Module.autoreqs[const] = path
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ #
42
+ # Patch 'Module#const_missing' to support 'autoreq'
43
+ #
44
+ class Module
45
+
46
+ @@autoreq_searching_for = nil
47
+
48
+ alias const_missing_without_autoreq const_missing
49
+
50
+ def const_missing(const)
51
+ return if const == @@autoreq_searching_for
52
+
53
+ if thing = autoreqs[const]
54
+ case thing
55
+ when String, Symbol
56
+ require thing
57
+ when Proc
58
+ Object.class_eval(&thing)
59
+ else
60
+ raise "Error: Don't know how to autoload a #{thing.class}: #{thing.inspect}"
61
+ end
62
+ end
63
+
64
+ @@autoreq_searching_for = const
65
+ const_get(const) || const_missing_without_autoreq(const)
66
+ end
67
+
68
+ def autoreqs
69
+ @@autoreqs ||= {}
70
+ end
71
+
16
72
  end
17
73
 
74
+
18
75
  ## Pretty error messages
19
76
  require_wrapper = proc do |mod|
20
77
  #p [:loading, mod]
@@ -23,5 +23,6 @@ autoload :Ratio, 'epitools/ratio'
23
23
  autoload :Sys, 'epitools/sys'
24
24
  autoload :ProgressBar, 'epitools/progressbar'
25
25
 
26
-
26
+ ## Gems
27
+ autoreq :MimeMagic, 'mimemagic'
27
28
 
@@ -483,7 +483,7 @@ module Enumerable
483
483
  def foldl(methodname=nil, &block)
484
484
  result = nil
485
485
 
486
- raise "Error: pass a parameter OR a block, not both!" if methodname and block
486
+ raise "Error: pass a parameter OR a block, not both!" unless !!methodname ^ block_given?
487
487
 
488
488
  if methodname
489
489
 
@@ -842,6 +842,19 @@ class Object
842
842
  end
843
843
  end
844
844
 
845
+ unless IO.respond_to? :copy_stream
846
+
847
+ class IO
848
+
849
+ def self.copy_stream(input, output)
850
+ while chunk = input.read(8192)
851
+ output.write(chunk)
852
+ end
853
+ end
854
+
855
+ end
856
+
857
+ end
845
858
 
846
859
  #
847
860
  # Emit a quick debug message (only if $DEBUG is true)
@@ -856,3 +869,5 @@ def dmsg(msg)
856
869
  end
857
870
  end
858
871
  end
872
+
873
+
@@ -133,7 +133,7 @@ class Browser
133
133
  #end
134
134
 
135
135
  # Determine the cache setting
136
- use_cache = options[:use_cache] || options[:cache] || options[:cached] || @use_cache
136
+ use_cache = (options[:cached] == false) ? false : @use_cache
137
137
 
138
138
  cached_already = cache.include?(url)
139
139
 
@@ -67,6 +67,8 @@ def lesspipe(*args)
67
67
  yield less
68
68
  end
69
69
  end
70
+
71
+ rescue Errno::EPIPE
70
72
  end
71
73
 
72
74
 
@@ -22,6 +22,9 @@ class Path
22
22
  end
23
23
  end
24
24
 
25
+ #
26
+ # TODO: Remove the tempfile when the Path object is garbage collected or freed.
27
+ #
25
28
  def self.tmpfile(prefix="tmp")
26
29
  path = Path[ Tempfile.new(prefix).path ]
27
30
  yield path if block_given?
@@ -111,7 +114,6 @@ class Path
111
114
  end
112
115
  end
113
116
 
114
-
115
117
  ## getters
116
118
 
117
119
  # The directories in the path, split into an array. (eg: ['usr', 'src', 'linux'])
@@ -153,6 +155,11 @@ class Path
153
155
  end
154
156
  end
155
157
 
158
+ def exts
159
+ extensions = basename.split('.')[1..-1]
160
+ extensions += [@ext] if @ext
161
+ extensions
162
+ end
156
163
 
157
164
  ## fstat info
158
165
 
@@ -245,6 +252,8 @@ class Path
245
252
  File.open(path, mode)
246
253
  end
247
254
  end
255
+ alias_method :io, :open
256
+ alias_method :stream, :open
248
257
 
249
258
  def read(length=nil, offset=nil)
250
259
  File.read(path, length, offset)
@@ -373,10 +382,63 @@ class Path
373
382
  def md5
374
383
  Digest::MD5.file(self).hexdigest
375
384
  end
376
-
377
385
  alias_method :md5sum, :md5
378
386
 
379
387
 
388
+ # http://ruby-doc.org/stdlib/libdoc/zlib/rdoc/index.html
389
+
390
+ def gzip
391
+ gz_filename = self.with(:filename=>filename+".gz")
392
+
393
+ raise "#{gz_filename} already exists" if gz_filename.exists?
394
+
395
+ open("rb") do |input|
396
+ Zlib::GzipWriter.open(gz_filename) do |gzip|
397
+ IO.copy_stream(input, gzip)
398
+ end
399
+ end
400
+
401
+ gz_filename
402
+ end
403
+
404
+ def gzip!
405
+ gzipped = self.gzip
406
+ self.rm
407
+ self.path = gzipped.path
408
+ end
409
+
410
+ def gunzip
411
+ raise "Not a .gz file" unless ext == "gz"
412
+
413
+ gunzipped = self.with(:ext=>nil)
414
+
415
+ gunzipped.open("wb") do |out|
416
+ Zlib::GzipReader.open(self) do |gunzip|
417
+ IO.copy_stream(gunzip, out)
418
+ end
419
+ end
420
+
421
+ gunzipped
422
+ end
423
+
424
+ def gunzip!
425
+ gunzipped = self.gunzip
426
+ self.rm
427
+ self.path = gunzipped.path
428
+ end
429
+
430
+ #
431
+ # Return the IO object for this file.
432
+ #
433
+ def io
434
+ open
435
+ end
436
+ alias_method :stream, :io
437
+
438
+ def =~(pattern)
439
+ path =~ pattern
440
+ end
441
+
380
442
  ## Class method versions of FileUtils-like things
381
443
 
382
444
  %w[
@@ -394,9 +456,40 @@ class Path
394
456
  end
395
457
  }
396
458
  end
459
+
460
+
461
+ # Mimetype finding and magic (requires 'mimemagic' gem)
462
+
463
+ #
464
+ # Find the file's mimetype (first from file extension, then by magic)
465
+ #
466
+ def mimetype
467
+ mimetype_from_ext || magic
468
+ end
469
+ alias_method :identify, :mimetype
470
+
471
+ #
472
+ # Find the file's mimetype (only using the file extension)
473
+ #
474
+ def mimetype_from_ext
475
+ MimeMagic.by_extension(ext)
476
+ end
477
+
478
+ #
479
+ # Find the file's mimetype (by magic)
480
+ #
481
+ def magic
482
+ open { |io| MimeMagic.by_magic(io) }
483
+ end
484
+
485
+ def ext_by_magic
486
+ # TODO: return the extension for the mime type.
487
+ raise NotImplementedError
488
+ end
397
489
 
398
490
  end
399
491
 
492
+
400
493
  #
401
494
  # A wrapper for URL objects
402
495
  #
@@ -14,11 +14,12 @@ require 'epitools'
14
14
  # zopen("otherfile.gz", "w") #=> #<Zlib::GzipWriter:0x7fe30448>>
15
15
  # zopen("test.txt.gz") { |f| f.read } # read the contents of the .gz file, then close the file handle automatically.
16
16
  #
17
- def zopen(filename, mode="r")
17
+ def zopen(path, mode="r")
18
18
 
19
- file = open(filename, mode)
19
+ path = Path[path] unless path.is_a? Path
20
+ file = path.open(mode)
20
21
 
21
- if filename =~ /\.gz$/
22
+ if path.ext == "gz"
22
23
  case mode
23
24
  when "r", "rb"
24
25
  file = Zlib::GzipReader.new(file)
@@ -287,6 +287,8 @@ describe Enumerable do
287
287
  a = [1,2,3,4]
288
288
  a.foldl(:+).should == a.sum
289
289
  %w[hi there].foldl(:+).should == "hithere"
290
+
291
+ [ [1],[2],[3],[4] ].foldl(:+).should == [1,2,3,4]
290
292
  end
291
293
 
292
294
  it "powersets" do
@@ -1,5 +1,4 @@
1
- require 'epitools/permutations'
2
- require 'epitools/path'
1
+ require 'epitools'
3
2
 
4
3
  describe Path do
5
4
 
@@ -216,4 +215,38 @@ describe Path do
216
215
  path.sha1.should == Path.sha1(path)
217
216
  end
218
217
 
218
+ it "gzips and gunzips" do
219
+ path = Path.tmpfile
220
+ 500.times { path << "whee" }
221
+
222
+ path.ext.should_not == "gz"
223
+ gzipped = path.gzip
224
+
225
+ before = path.size
226
+ after = gzipped.size
227
+ before.should > after
228
+ gzipped.ext.should == "gz"
229
+
230
+ gunzipped = gzipped.gunzip
231
+ gunzipped.size.should == before
232
+ gunzipped.should == path
233
+ end
234
+
235
+ it "exts" do
236
+ path = Path["file.tar.gz"]
237
+ path.ext.should == "gz"
238
+ path.exts.should == ["tar", "gz"]
239
+ end
240
+
241
+ it "ios and streams" do
242
+ path = Path.tmpfile
243
+ f = open(path)
244
+ f.inspect.should == path.io.inspect
245
+ f.inspect.should == path.stream.inspect
246
+ end
247
+
248
+ it "mimes" do
249
+ Path[__FILE__].mimetype == "application/x-ruby"
250
+ end
251
+
219
252
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: epitools
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.37
5
+ version: 0.4.38
6
6
  platform: ruby
7
7
  authors:
8
8
  - epitron
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-29 00:00:00 -04:00
13
+ date: 2011-06-07 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency